3535//! fn main() {
3636//! let mut builder = Builder::new();
3737//! builder.set_network(Network::Testnet);
38- //! builder.set_esplora_server_url ("https://blockstream.info/testnet/api".to_string());
38+ //! builder.set_esplora_server ("https://blockstream.info/testnet/api".to_string());
3939//!
4040//! let node = builder.build();
4141//! node.start().unwrap();
@@ -161,6 +161,13 @@ use std::time::{Duration, Instant, SystemTime};
161161
162162uniffi:: include_scaffolding!( "ldk_node" ) ;
163163
164+ // Config defaults
165+ const DEFAULT_STORAGE_DIR_PATH : & str = "/tmp/ldk_node/" ;
166+ const DEFAULT_NETWORK : Network = Network :: Regtest ;
167+ const DEFAULT_LISTENING_ADDR : & str = "0.0.0.0:9735" ;
168+ const DEFAULT_CLTV_EXPIRY_DELTA : u32 = 144 ;
169+ const DEFAULT_ESPLORA_SERVER_URL : & str = "https://blockstream.info/api" ;
170+
164171// The 'stop gap' parameter used by BDK's wallet sync. This seems to configure the threshold
165172// number of blocks after which BDK stops looking for scripts belonging to the wallet.
166173const BDK_CLIENT_STOP_GAP : usize = 20 ;
@@ -185,11 +192,19 @@ const WALLET_KEYS_SEED_LEN: usize = 64;
185192
186193#[ derive( Debug , Clone ) ]
187194/// Represents the configuration of an [`Node`] instance.
195+ ///
196+ /// ### Defaults
197+ ///
198+ /// | Parameter | Value |
199+ /// |-----------------------------|------------------|
200+ /// | `storage_dir_path` | /tmp/ldk_node/ |
201+ /// | `network` | Network::Regtest |
202+ /// | `listening_address` | 0.0.0.0:9735 |
203+ /// | `default_cltv_expiry_delta` | 144 |
204+ ///
188205pub struct Config {
189206 /// The path where the underlying LDK and BDK persist their data.
190207 pub storage_dir_path : String ,
191- /// The URL of the utilized Esplora server.
192- pub esplora_server_url : String ,
193208 /// The used Bitcoin network.
194209 pub network : Network ,
195210 /// The IP address and TCP port the node will listen on.
@@ -201,15 +216,19 @@ pub struct Config {
201216impl Default for Config {
202217 fn default ( ) -> Self {
203218 Self {
204- storage_dir_path : "/tmp/ldk_node/" . to_string ( ) ,
205- esplora_server_url : "http://localhost:3002" . to_string ( ) ,
206- network : Network :: Regtest ,
207- listening_address : Some ( "0.0.0.0:9735" . parse ( ) . unwrap ( ) ) ,
208- default_cltv_expiry_delta : 144 ,
219+ storage_dir_path : DEFAULT_STORAGE_DIR_PATH . to_string ( ) ,
220+ network : DEFAULT_NETWORK ,
221+ listening_address : Some ( DEFAULT_LISTENING_ADDR . parse ( ) . unwrap ( ) ) ,
222+ default_cltv_expiry_delta : DEFAULT_CLTV_EXPIRY_DELTA ,
209223 }
210224 }
211225}
212226
227+ #[ derive( Debug , Clone ) ]
228+ enum ChainDataSourceConfig {
229+ Esplora ( String ) ,
230+ }
231+
213232#[ derive( Debug , Clone ) ]
214233enum EntropySourceConfig {
215234 SeedFile ( String ) ,
@@ -225,10 +244,16 @@ enum GossipSourceConfig {
225244
226245/// A builder for an [`Node`] instance, allowing to set some configuration and module choices from
227246/// the getgo.
247+ ///
248+ /// ### Defaults
249+ /// - Wallet entropy is sourced from a `keys_seed` file located under [`Config::storage_dir_path`]
250+ /// - Chain data is sourced from the Esplora endpoint `https://blockstream.info/api`
251+ /// - Gossip data is sourced via the peer-to-peer network
228252#[ derive( Debug ) ]
229253pub struct Builder {
230254 config : RwLock < Config > ,
231255 entropy_source_config : RwLock < Option < EntropySourceConfig > > ,
256+ chain_data_source_config : RwLock < Option < ChainDataSourceConfig > > ,
232257 gossip_source_config : RwLock < Option < GossipSourceConfig > > ,
233258}
234259
@@ -237,16 +262,18 @@ impl Builder {
237262 pub fn new ( ) -> Self {
238263 let config = RwLock :: new ( Config :: default ( ) ) ;
239264 let entropy_source_config = RwLock :: new ( None ) ;
265+ let chain_data_source_config = RwLock :: new ( None ) ;
240266 let gossip_source_config = RwLock :: new ( None ) ;
241- Self { config, entropy_source_config, gossip_source_config }
267+ Self { config, entropy_source_config, chain_data_source_config , gossip_source_config }
242268 }
243269
244270 /// Creates a new builder instance from an [`Config`].
245271 pub fn from_config ( config : Config ) -> Self {
246272 let config = RwLock :: new ( config) ;
247273 let entropy_source_config = RwLock :: new ( None ) ;
274+ let chain_data_source_config = RwLock :: new ( None ) ;
248275 let gossip_source_config = RwLock :: new ( None ) ;
249- Self { config, entropy_source_config, gossip_source_config }
276+ Self { config, entropy_source_config, chain_data_source_config , gossip_source_config }
250277 }
251278
252279 /// Configures the [`Node`] instance to source its wallet entropy from a seed file on disk.
@@ -278,6 +305,12 @@ impl Builder {
278305 Some ( EntropySourceConfig :: Bip39Mnemonic { mnemonic, passphrase } ) ;
279306 }
280307
308+ /// Configures the [`Node`] instance to source its chain data from the given Esplora server.
309+ pub fn set_esplora_server ( & self , esplora_server_url : String ) {
310+ * self . chain_data_source_config . write ( ) . unwrap ( ) =
311+ Some ( ChainDataSourceConfig :: Esplora ( esplora_server_url) ) ;
312+ }
313+
281314 /// Configures the [`Node`] instance to source its gossip data from the Lightning peer-to-peer
282315 /// network.
283316 pub fn set_gossip_source_p2p ( & self ) {
@@ -292,30 +325,18 @@ impl Builder {
292325 }
293326
294327 /// Sets the used storage directory path.
295- ///
296- /// Default: `/tmp/ldk_node/`
297328 pub fn set_storage_dir_path ( & self , storage_dir_path : String ) {
298329 let mut config = self . config . write ( ) . unwrap ( ) ;
299330 config. storage_dir_path = storage_dir_path;
300331 }
301332
302- /// Sets the Esplora server URL.
303- ///
304- /// Default: `https://blockstream.info/api`
305- pub fn set_esplora_server_url ( & self , esplora_server_url : String ) {
306- let mut config = self . config . write ( ) . unwrap ( ) ;
307- config. esplora_server_url = esplora_server_url;
308- }
309-
310333 /// Sets the Bitcoin network used.
311334 pub fn set_network ( & self , network : Network ) {
312335 let mut config = self . config . write ( ) . unwrap ( ) ;
313336 config. network = network;
314337 }
315338
316339 /// Sets the IP address and TCP port on which [`Node`] will listen for incoming network connections.
317- ///
318- /// Default: `0.0.0.0:9735`
319340 pub fn set_listening_address ( & self , listening_address : NetAddress ) {
320341 let mut config = self . config . write ( ) . unwrap ( ) ;
321342 config. listening_address = Some ( listening_address) ;
@@ -347,24 +368,20 @@ impl Builder {
347368 let logger = Arc :: new ( FilesystemLogger :: new ( log_file_path) ) ;
348369
349370 // Initialize the on-chain wallet and chain access
350- let seed_bytes = if let Some ( entropy_source_config) =
351- & * self . entropy_source_config . read ( ) . unwrap ( )
352- {
353- // Use the configured entropy source, if the user set one.
354- match entropy_source_config {
355- EntropySourceConfig :: SeedBytes ( bytes ) => bytes . clone ( ) ,
356- EntropySourceConfig :: SeedFile ( seed_path ) => {
357- io :: utils :: read_or_generate_seed_file ( seed_path )
358- }
359- EntropySourceConfig :: Bip39Mnemonic { mnemonic , passphrase } => match passphrase {
360- Some ( passphrase ) => mnemonic . to_seed ( passphrase ) ,
361- None => mnemonic . to_seed ( "" ) ,
362- } ,
371+ let seed_bytes = match & * self . entropy_source_config . read ( ) . unwrap ( ) {
372+ Some ( EntropySourceConfig :: SeedBytes ( bytes ) ) => bytes . clone ( ) ,
373+ Some ( EntropySourceConfig :: SeedFile ( seed_path ) ) => {
374+ io :: utils :: read_or_generate_seed_file ( seed_path )
375+ }
376+ Some ( EntropySourceConfig :: Bip39Mnemonic { mnemonic , passphrase } ) => match passphrase {
377+ Some ( passphrase ) => mnemonic . to_seed ( passphrase ) ,
378+ None => mnemonic . to_seed ( "" ) ,
379+ } ,
380+ None => {
381+ // Default to read or generate from the default location generate a seed file.
382+ let seed_path = format ! ( "{}/keys_seed" , config . storage_dir_path ) ;
383+ io :: utils :: read_or_generate_seed_file ( & seed_path )
363384 }
364- } else {
365- // Default to read or generate from the default location generate a seed file.
366- let seed_path = format ! ( "{}/keys_seed" , config. storage_dir_path) ;
367- io:: utils:: read_or_generate_seed_file ( & seed_path)
368385 } ;
369386
370387 let xprv = bitcoin:: util:: bip32:: ExtendedPrivKey :: new_master ( config. network , & seed_bytes)
@@ -389,14 +406,25 @@ impl Builder {
389406 )
390407 . expect ( "Failed to set up on-chain wallet" ) ;
391408
392- let tx_sync = Arc :: new ( EsploraSyncClient :: new (
393- config. esplora_server_url . clone ( ) ,
394- Arc :: clone ( & logger) ,
395- ) ) ;
396-
397- let blockchain =
398- EsploraBlockchain :: from_client ( tx_sync. client ( ) . clone ( ) , BDK_CLIENT_STOP_GAP )
399- . with_concurrency ( BDK_CLIENT_CONCURRENCY ) ;
409+ let ( blockchain, tx_sync) = match & * self . chain_data_source_config . read ( ) . unwrap ( ) {
410+ Some ( ChainDataSourceConfig :: Esplora ( server_url) ) => {
411+ let tx_sync =
412+ Arc :: new ( EsploraSyncClient :: new ( server_url. clone ( ) , Arc :: clone ( & logger) ) ) ;
413+ let blockchain =
414+ EsploraBlockchain :: from_client ( tx_sync. client ( ) . clone ( ) , BDK_CLIENT_STOP_GAP )
415+ . with_concurrency ( BDK_CLIENT_CONCURRENCY ) ;
416+ ( blockchain, tx_sync)
417+ }
418+ None => {
419+ // Default to Esplora client.
420+ let server_url = DEFAULT_ESPLORA_SERVER_URL . to_string ( ) ;
421+ let tx_sync = Arc :: new ( EsploraSyncClient :: new ( server_url, Arc :: clone ( & logger) ) ) ;
422+ let blockchain =
423+ EsploraBlockchain :: from_client ( tx_sync. client ( ) . clone ( ) , BDK_CLIENT_STOP_GAP )
424+ . with_concurrency ( BDK_CLIENT_CONCURRENCY ) ;
425+ ( blockchain, tx_sync)
426+ }
427+ } ;
400428
401429 let runtime = Arc :: new ( RwLock :: new ( None ) ) ;
402430 let wallet = Arc :: new ( Wallet :: new (
0 commit comments