diff --git a/examples/repl.rs b/examples/repl.rs index 69eca920..09e75f9e 100644 --- a/examples/repl.rs +++ b/examples/repl.rs @@ -95,6 +95,9 @@ fn main() { let config = match matches.value_of("esplora") { Some(base_url) => AnyBlockchainConfig::Esplora(EsploraBlockchainConfig { base_url: base_url.to_string(), + concurrency: matches + .value_of("esplora_concurrency") + .and_then(|v| v.parse::().ok()), }), None => AnyBlockchainConfig::Electrum(ElectrumBlockchainConfig { url: matches.value_of("server").unwrap().to_string(), diff --git a/src/blockchain/any.rs b/src/blockchain/any.rs index 1fc987f4..09b7c4b5 100644 --- a/src/blockchain/any.rs +++ b/src/blockchain/any.rs @@ -52,7 +52,7 @@ //! //! # #[cfg(feature = "esplora")] //! # { -//! let esplora_blockchain = EsploraBlockchain::new("..."); +//! let esplora_blockchain = EsploraBlockchain::new("...", None); //! let wallet_esplora: Wallet = Wallet::new( //! "...", //! None, diff --git a/src/blockchain/esplora.rs b/src/blockchain/esplora.rs index d236e28f..417dcf8c 100644 --- a/src/blockchain/esplora.rs +++ b/src/blockchain/esplora.rs @@ -31,7 +31,7 @@ //! //! ```no_run //! # use bdk::blockchain::esplora::EsploraBlockchain; -//! let blockchain = EsploraBlockchain::new("https://blockstream.info/testnet/api"); +//! let blockchain = EsploraBlockchain::new("https://blockstream.info/testnet/api", None); //! # Ok::<(), bdk::Error>(()) //! ``` @@ -59,7 +59,7 @@ use crate::error::Error; use crate::wallet::utils::ChunksIterator; use crate::FeeRate; -const CONCURRENT: usize = 4; +const DEFAULT_CONCURRENT_REQUESTS: u8 = 4; #[derive(Debug)] struct UrlClient { @@ -67,6 +67,7 @@ struct UrlClient { // We use the async client instead of the blocking one because it automatically uses `fetch` // when the target platform is wasm32. client: Client, + concurrency: u8, } /// Structure that implements the logic to sync with Esplora @@ -84,10 +85,11 @@ impl std::convert::From for EsploraBlockchain { impl EsploraBlockchain { /// Create a new instance of the client from a base URL - pub fn new(base_url: &str) -> Self { + pub fn new(base_url: &str, concurrency: Option) -> Self { EsploraBlockchain(UrlClient { url: base_url.to_string(), client: Client::new(), + concurrency: concurrency.unwrap_or(DEFAULT_CONCURRENT_REQUESTS), }) } } @@ -305,7 +307,7 @@ impl ElectrumLikeSync for UrlClient { ) -> Result>, Error> { let future = async { let mut results = vec![]; - for chunk in ChunksIterator::new(scripts.into_iter(), CONCURRENT) { + for chunk in ChunksIterator::new(scripts.into_iter(), self.concurrency as usize) { let mut futs = FuturesOrdered::new(); for script in chunk { futs.push(self._script_get_history(&script)); @@ -325,7 +327,7 @@ impl ElectrumLikeSync for UrlClient { ) -> Result, Error> { let future = async { let mut results = vec![]; - for chunk in ChunksIterator::new(txids.into_iter(), CONCURRENT) { + for chunk in ChunksIterator::new(txids.into_iter(), self.concurrency as usize) { let mut futs = FuturesOrdered::new(); for txid in chunk { futs.push(self._get_tx_no_opt(&txid)); @@ -345,7 +347,7 @@ impl ElectrumLikeSync for UrlClient { ) -> Result, Error> { let future = async { let mut results = vec![]; - for chunk in ChunksIterator::new(heights.into_iter(), CONCURRENT) { + for chunk in ChunksIterator::new(heights.into_iter(), self.concurrency as usize) { let mut futs = FuturesOrdered::new(); for height in chunk { futs.push(self._get_header(height)); @@ -404,13 +406,17 @@ impl Into for EsploraHeader { #[derive(Debug, serde::Deserialize, serde::Serialize)] pub struct EsploraBlockchainConfig { pub base_url: String, + pub concurrency: Option, } impl ConfigurableBlockchain for EsploraBlockchain { type Config = EsploraBlockchainConfig; fn from_config(config: &Self::Config) -> Result { - Ok(EsploraBlockchain::new(config.base_url.as_str())) + Ok(EsploraBlockchain::new( + config.base_url.as_str(), + config.concurrency, + )) } } diff --git a/src/cli.rs b/src/cli.rs index 06c11d46..350614ee 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -362,14 +362,23 @@ pub fn add_global_flags<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { ); if cfg!(feature = "esplora") { - app = app.arg( - Arg::with_name("esplora") - .short("e") - .long("esplora") - .value_name("ESPLORA") - .help("Use the esplora server if given as parameter") - .takes_value(true), - ); + app = app + .arg( + Arg::with_name("esplora") + .short("e") + .long("esplora") + .value_name("ESPLORA") + .help("Use the esplora server if given as parameter") + .takes_value(true), + ) + .arg( + Arg::with_name("esplora_concurrency") + .long("esplora_concurrency") + .value_name("ESPLORA_CONCURRENCY") + .help("Concurrency of requests made to the esplora server") + .default_value("4") + .takes_value(true), + ) } if cfg!(feature = "electrum") {