A ready-to-go Lightning node library built using LDK and BDK.
LDK Node is a self-custodial Lightning node in library form. Its central goal is to provide a small, simple, and straightforward interface that enables users to easily set up and run a Lightning node with an integrated on-chain wallet. While minimalism is at its core, LDK Node aims to be sufficiently modular and configurable to be useful for a variety of use cases.
The primary abstraction of the library is the Node, which can be retrieved by setting up and configuring a Builder to your liking and calling one of the build methods. Node can then be controlled via commands such as start, stop, open_channel, send, etc.
use ldk_node::Builder;
use ldk_node::lightning_invoice::Bolt11Invoice;
use ldk_node::lightning::ln::msgs::SocketAddress;
use ldk_node::bitcoin::secp256k1::PublicKey;
use ldk_node::bitcoin::Network;
use std::str::FromStr;
fn main() {
let mut builder = Builder::new();
builder.set_network(Network::Testnet);
builder.set_chain_source_esplora("https://blockstream.info/testnet/api".to_string(), None);
builder.set_gossip_source_rgs("https://rapidsync.lightningdevkit.org/testnet/snapshot".to_string());
let node = builder.build().unwrap();
node.start().unwrap();
let funding_address = node.onchain_payment().new_address();
// .. fund address ..
let node_id = PublicKey::from_str("NODE_ID").unwrap();
let node_addr = SocketAddress::from_str("IP_ADDR:PORT").unwrap();
node.open_channel(node_id, node_addr, 10000, None, None).unwrap();
let event = node.wait_next_event();
println!("EVENT: {:?}", event);
node.event_handled();
let invoice = Bolt11Invoice::from_str("INVOICE_STR").unwrap();
node.bolt11_payment().send(&invoice, None).unwrap();
node.stop().unwrap();
}LDK Node currently comes with a decidedly opinionated set of design choices:
- On-chain data is handled by the integrated BDK wallet.
- Chain data may currently be sourced from the Bitcoin Core RPC interface, or from an Electrum or Esplora server.
- Wallet and channel state may be persisted to an SQLite database, to file system, or to a custom back-end to be implemented by the user.
- Gossip data may be sourced via Lightning's peer-to-peer network or the Rapid Gossip Sync protocol.
- Entropy for the Lightning and on-chain wallets may be sourced from raw bytes or a BIP39 mnemonic. In addition, LDK Node offers the means to generate and persist the entropy bytes to disk.
OnchainPayment::send_to_address_with_broadcast_result and
send_all_to_address_with_broadcast_result submit a signed transaction directly to the
configured chain source. They return Accepted { txid } only when that backend acknowledges
the submitted transaction. Rejected { txid, reason } records a recognized refusal response;
Unknown { txid } covers a lost or ambiguous result. Both retain the locally computed txid.
Neither a refusal nor an unknown result proves the transaction was never delivered, so callers
must not create a replacement payment from either result. Backend acknowledgement is not
confirmation or guaranteed network propagation. An Err from these methods means this call did
not initiate broadcast.
The existing send_to_address and send_all_to_address methods still return a local txid after
attempting queue admission, even if admission fails. Their returned txid gives no backend
acceptance assurance. The on-chain variant of
UnifiedQrPayment::send has the same queueing semantics.
LDK Node itself is written in Rust and may therefore be natively added as a library dependency to any std Rust program. However, beyond its Rust API it also offers language bindings for Swift, Kotlin, and Python based on the UniFFI. Moreover, Flutter bindings are also available.
The Minimum Supported Rust Version (MSRV) is currently 1.85.0.