diff --git a/crates/bdk/src/wallet/error.rs b/crates/bdk/src/wallet/error.rs
index db58fef06f..a90083fa12 100644
--- a/crates/bdk/src/wallet/error.rs
+++ b/crates/bdk/src/wallet/error.rs
@@ -44,9 +44,9 @@ impl fmt::Display for MiniscriptPsbtError {
impl std::error::Error for MiniscriptPsbtError {}
#[derive(Debug)]
-/// Error returned from [`TxBuilder::finish`]
+/// Error returned by [`TxBuilder::finish`]
///
-/// [`TxBuilder::finish`]: crate::wallet::tx_builder::TxBuilder::finish
+/// [`TxBuilder::finish`]: super::tx_builder::TxBuilder::finish
pub enum CreateTxError
{
/// There was a problem with the descriptors passed in
Descriptor(DescriptorError),
@@ -246,9 +246,7 @@ impl
From for CreateTxError {
impl std::error::Error for CreateTxError {}
#[derive(Debug)]
-/// Error returned from [`Wallet::build_fee_bump`]
-///
-/// [`Wallet::build_fee_bump`]: super::Wallet::build_fee_bump
+/// Error returned by [`Wallet::build_fee_bump`]
pub enum BuildFeeBumpError {
/// Happens when trying to spend an UTXO that is not in the internal database
UnknownUtxo(OutPoint),
diff --git a/crates/bdk/src/wallet/mod.rs b/crates/bdk/src/wallet/mod.rs
index 2177a88c47..b7a1f5e07f 100644
--- a/crates/bdk/src/wallet/mod.rs
+++ b/crates/bdk/src/wallet/mod.rs
@@ -41,6 +41,7 @@ use core::ops::Deref;
use descriptor::error::Error as DescriptorError;
use miniscript::psbt::{PsbtExt, PsbtInputExt, PsbtInputSatisfier};
+use bdk_chain::request::{FullScanRequest, SyncRequest};
use bdk_chain::tx_graph::CalculateFeeError;
pub mod coin_selection;
@@ -109,6 +110,38 @@ pub struct Update {
pub chain: Option,
}
+impl
+ From<(
+ BTreeMap,
+ TxGraph,
+ local_chain::Update,
+ )> for Update
+{
+ fn from(
+ (last_active_indices, graph, chain): (
+ BTreeMap,
+ TxGraph,
+ local_chain::Update,
+ ),
+ ) -> Self {
+ Self {
+ last_active_indices,
+ graph,
+ chain: Some(chain),
+ }
+ }
+}
+
+impl From<(TxGraph, local_chain::Update)> for Update {
+ fn from((graph, chain): (TxGraph, local_chain::Update)) -> Self {
+ Self {
+ graph,
+ chain: Some(chain),
+ ..Default::default()
+ }
+ }
+}
+
/// The changes made to a wallet by applying an [`Update`].
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, Default)]
pub struct ChangeSet {
@@ -2353,6 +2386,70 @@ impl Wallet {
pub fn local_chain(&self) -> &LocalChain {
&self.chain
}
+
+ /// Create a [`SyncRequest`] for this wallet.
+ ///
+ /// This is the first step when performing a spk-based wallet sync, the returned [`SyncRequest`] collects
+ /// the wallet keychain all or unused script pub keys, unconfirmed transaction id, UTXOs and local
+ /// chain checkpoint data needed to start a blockchain sync with a blockchain client. For a faster
+ /// sync set `unused_spks_only` to true to only get updates for unused wallet script pub keys (addresses).
+ pub fn sync_request(&self, unused_spks_only: bool) -> SyncRequest {
+ let checkpoint = self.latest_checkpoint();
+
+ // Sync only unused SPKs
+ let spks = if unused_spks_only {
+ self.spk_index()
+ .unused_spks()
+ .map(|(_keychain, _index, script)| ScriptBuf::from(script))
+ .collect::>()
+ }
+ // Sync all SPKs
+ else {
+ self.spk_index()
+ .revealed_spks()
+ .map(|(_keychain, _index, script)| ScriptBuf::from(script))
+ .collect::>()
+ };
+
+ // Sync UTXOs
+ // We want to search for whether our UTXOs are spent, and spent by which transaction.
+ let outpoints: Vec = self.list_unspent().map(|utxo| utxo.outpoint).collect();
+
+ // Sync unconfirmed TX
+ // We want to search for whether our unconfirmed transactions are now confirmed.
+ let txids: Vec = self
+ .transactions()
+ .filter(|canonical_tx| !canonical_tx.chain_position.is_confirmed())
+ .map(|canonical_tx| canonical_tx.tx_node.txid)
+ .collect();
+
+ SyncRequest {
+ spks,
+ txids,
+ outpoints,
+ checkpoint,
+ }
+ }
+
+ /// Create a [`FullScanRequest] for this wallet.
+ ///
+ /// This is the first step when performing a spk-based wallet full scan, the returned [`FullScanRequest]
+ /// collects iterators for the wallet's keychain script pub keys, and local chain checkpoint
+ /// data needed to start a blockchain full scan with a blockchain client.
+ ///
+ /// This operation is generally only used when importing or restoring a previously used wallet
+ /// in which the list of used scripts is not known.
+ pub fn full_scan_request(
+ &self,
+ ) -> FullScanRequest + Clone> {
+ let spks_by_keychain = self.all_unbounded_spk_iters();
+ let checkpoint = self.latest_checkpoint();
+
+ FullScanRequest {
+ spks_by_keychain,
+ checkpoint,
+ }
+ }
}
impl AsRef> for Wallet {
diff --git a/example-crates/wallet_esplora_async/.gitignore b/example-crates/wallet_esplora_async/.gitignore
new file mode 100644
index 0000000000..630a732ef2
--- /dev/null
+++ b/example-crates/wallet_esplora_async/.gitignore
@@ -0,0 +1 @@
+bdk_wallet_esplora_async_example.dat
diff --git a/example-crates/wallet_esplora_blocking/.gitignore b/example-crates/wallet_esplora_blocking/.gitignore
new file mode 100644
index 0000000000..630a732ef2
--- /dev/null
+++ b/example-crates/wallet_esplora_blocking/.gitignore
@@ -0,0 +1 @@
+bdk_wallet_esplora_async_example.dat