///
/// ## Example
/// See the [`blockchain::electrum`](crate::blockchain::electrum) module for a usage example.
-pub struct ElectrumBlockchain(Client);
+pub struct ElectrumBlockchain {
+ client: Client,
+ stop_gap: usize,
+}
impl std::convert::From<Client> for ElectrumBlockchain {
fn from(client: Client) -> Self {
- ElectrumBlockchain(client)
+ ElectrumBlockchain {
+ client,
+ stop_gap: 20,
+ }
}
}
fn setup<D: BatchDatabase, P: Progress>(
&self,
- stop_gap: Option<usize>,
+ _stop_gap: Option<usize>,
database: &mut D,
progress_update: P,
) -> Result<(), Error> {
- self.0
- .electrum_like_setup(stop_gap, database, progress_update)
+ self.client
+ .electrum_like_setup(Some(self.stop_gap), database, progress_update)
}
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
- Ok(self.0.transaction_get(txid).map(Option::Some)?)
+ Ok(self.client.transaction_get(txid).map(Option::Some)?)
}
fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
- Ok(self.0.transaction_broadcast(tx).map(|_| ())?)
+ Ok(self.client.transaction_broadcast(tx).map(|_| ())?)
}
fn get_height(&self) -> Result<u32, Error> {
// TODO: unsubscribe when added to the client, or is there a better call to use here?
Ok(self
- .0
+ .client
.block_headers_subscribe()
.map(|data| data.height as u32)?)
}
fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
Ok(FeeRate::from_btc_per_kvb(
- self.0.estimate_fee(target)? as f32
+ self.client.estimate_fee(target)? as f32
))
}
}
pub retry: u8,
/// Request timeout (seconds)
pub timeout: Option<u8>,
+ /// Stop searching addresses for transactions after finding an unused gap of this length
+ pub stop_gap: usize,
}
impl ConfigurableBlockchain for ElectrumBlockchain {
.socks5(socks5)?
.build();
- Ok(ElectrumBlockchain(Client::from_config(
- config.url.as_str(),
- electrum_config,
- )?))
+ Ok(ElectrumBlockchain {
+ client: Client::from_config(config.url.as_str(), electrum_config)?,
+ stop_gap: config.stop_gap,
+ })
}
}
use std::collections::{HashMap, HashSet};
use std::fmt;
-use futures::stream::{self, FuturesOrdered, StreamExt, TryStreamExt};
-
-#[allow(unused_imports)]
-use log::{debug, error, info, trace};
-
-use serde::Deserialize;
-
-use reqwest::{Client, StatusCode};
-
use bitcoin::consensus::{self, deserialize, serialize};
use bitcoin::hashes::hex::{FromHex, ToHex};
use bitcoin::hashes::{sha256, Hash};
use bitcoin::{BlockHash, BlockHeader, Script, Transaction, Txid};
+use futures::stream::{self, FuturesOrdered, StreamExt, TryStreamExt};
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+use reqwest::{Client, StatusCode};
+use serde::Deserialize;
-use self::utils::{ElectrumLikeSync, ElsGetHistoryRes};
-use super::*;
use crate::database::BatchDatabase;
use crate::error::Error;
use crate::wallet::utils::ChunksIterator;
use crate::FeeRate;
+use super::*;
+
+use self::utils::{ElectrumLikeSync, ElsGetHistoryRes};
+
const DEFAULT_CONCURRENT_REQUESTS: u8 = 4;
#[derive(Debug)]
/// ## Example
/// See the [`blockchain::esplora`](crate::blockchain::esplora) module for a usage example.
#[derive(Debug)]
-pub struct EsploraBlockchain(UrlClient);
+pub struct EsploraBlockchain {
+ url_client: UrlClient,
+ stop_gap: usize,
+}
impl std::convert::From<UrlClient> for EsploraBlockchain {
fn from(url_client: UrlClient) -> Self {
- EsploraBlockchain(url_client)
+ EsploraBlockchain {
+ url_client,
+ stop_gap: 20,
+ }
}
}
impl EsploraBlockchain {
/// Create a new instance of the client from a base URL
- pub fn new(base_url: &str, concurrency: Option<u8>) -> Self {
- EsploraBlockchain(UrlClient {
- url: base_url.to_string(),
- client: Client::new(),
- concurrency: concurrency.unwrap_or(DEFAULT_CONCURRENT_REQUESTS),
- })
+ pub fn new(base_url: &str, concurrency: Option<u8>, stop_gap: usize) -> Self {
+ EsploraBlockchain {
+ url_client: UrlClient {
+ url: base_url.to_string(),
+ client: Client::new(),
+ concurrency: concurrency.unwrap_or(DEFAULT_CONCURRENT_REQUESTS),
+ },
+ stop_gap,
+ }
}
}
progress_update: P,
) -> Result<(), Error> {
maybe_await!(self
- .0
+ .url_client
.electrum_like_setup(stop_gap, database, progress_update))
}
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
- Ok(await_or_block!(self.0._get_tx(txid))?)
+ Ok(await_or_block!(self.url_client._get_tx(txid))?)
}
fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
- Ok(await_or_block!(self.0._broadcast(tx))?)
+ Ok(await_or_block!(self.url_client._broadcast(tx))?)
}
fn get_height(&self) -> Result<u32, Error> {
- Ok(await_or_block!(self.0._get_height())?)
+ Ok(await_or_block!(self.url_client._get_height())?)
}
fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
- let estimates = await_or_block!(self.0._get_fee_estimates())?;
+ let estimates = await_or_block!(self.url_client._get_fee_estimates())?;
let fee_val = estimates
.into_iter()
pub base_url: String,
/// Number of parallel requests sent to the esplora service (default: 4)
pub concurrency: Option<u8>,
+ /// Stop searching addresses for transactions after finding an unused gap of this length
+ pub stop_gap: usize,
}
impl ConfigurableBlockchain for EsploraBlockchain {
Ok(EsploraBlockchain::new(
config.base_url.as_str(),
config.concurrency,
+ config.stop_gap,
))
}
}