Skip to content

Commit

Permalink
feat(wallet): add sync_request and full_scan_request functions
Browse files Browse the repository at this point in the history
  • Loading branch information
notmandatory committed Feb 2, 2024
1 parent dd02f8a commit 125bc4a
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 5 deletions.
8 changes: 3 additions & 5 deletions crates/bdk/src/wallet/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<P> {
/// There was a problem with the descriptors passed in
Descriptor(DescriptorError),
Expand Down Expand Up @@ -246,9 +246,7 @@ impl<P> From<coin_selection::Error> for CreateTxError<P> {
impl<P: core::fmt::Display + core::fmt::Debug> std::error::Error for CreateTxError<P> {}

#[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),
Expand Down
65 changes: 65 additions & 0 deletions crates/bdk/src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ use core::ops::Deref;
use descriptor::error::Error as DescriptorError;
use miniscript::psbt::{PsbtExt, PsbtInputExt, PsbtInputSatisfier};

use bdk_chain::spk_client::{FullScanRequest, SyncRequest};
use bdk_chain::tx_graph::CalculateFeeError;

pub mod coin_selection;
Expand Down Expand Up @@ -2485,6 +2486,70 @@ impl<D> Wallet<D> {
.batch_insert_relevant_unconfirmed(unconfirmed_txs);
self.persist.stage(ChangeSet::from(indexed_graph_changeset));
}

/// 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 local_chain = self.local_chain().clone();

// Sync only unused SPKs
let spks = if unused_spks_only {
self.spk_index()
.unused_spks()
.map(|(_keychain, _index, script)| ScriptBuf::from(script))
.collect::<Vec<ScriptBuf>>()
}
// Sync all SPKs
else {
self.spk_index()
.revealed_spks()
.map(|(_keychain, _index, script)| ScriptBuf::from(script))
.collect::<Vec<ScriptBuf>>()
};

// Sync UTXOs
// We want to search for whether our UTXOs are spent, and spent by which transaction.
let outpoints: Vec<OutPoint> = 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<Txid> = self
.transactions()
.filter(|canonical_tx| !canonical_tx.chain_position.is_confirmed())
.map(|canonical_tx| canonical_tx.tx_node.txid)
.collect();

SyncRequest {
spks,
txids,
outpoints,
local_chain,
}
}

/// 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<KeychainKind, impl Iterator<Item = (u32, ScriptBuf)> + Clone> {
let spks_by_keychain = self.all_unbounded_spk_iters();
let local_chain = self.local_chain().clone();

FullScanRequest {
spks_by_keychain,
local_chain,
}
}
}

impl<D> AsRef<bdk_chain::tx_graph::TxGraph<ConfirmationTimeHeightAnchor>> for Wallet<D> {
Expand Down

0 comments on commit 125bc4a

Please sign in to comment.