From 4c52f3e08e85e73db379ee3411cceb8dbcec92e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BF=97=E5=AE=87?= Date: Wed, 24 Apr 2024 16:54:03 +0800 Subject: [PATCH] feat(wallet): make wallet compatible with sync/full-scan structures * Changed `Wallet::apply_update` to also take in anything that implements `Into`. This allows us to directly apply a `FullScanResult` or `SyncResult`. * Added `start_full_scan` and `start_sync_with_revealed_spks` methods to `Wallet`. Co-authored-by: Steve Myers --- crates/bdk/src/wallet/mod.rs | 49 +++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/crates/bdk/src/wallet/mod.rs b/crates/bdk/src/wallet/mod.rs index 1e24dd50..b959a3ad 100644 --- a/crates/bdk/src/wallet/mod.rs +++ b/crates/bdk/src/wallet/mod.rs @@ -26,6 +26,7 @@ use bdk_chain::{ local_chain::{ self, ApplyHeaderError, CannotConnectError, CheckPoint, CheckPointIter, LocalChain, }, + spk_client::{FullScanRequest, FullScanResult, SyncRequest, SyncResult}, tx_graph::{CanonicalTx, TxGraph}, Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeHeightAnchor, FullTxOut, IndexedTxGraph, Persist, PersistBackend, @@ -110,6 +111,26 @@ pub struct Update { pub chain: Option, } +impl From> for Update { + fn from(value: FullScanResult) -> Self { + Self { + last_active_indices: value.last_active_indices, + graph: value.graph_update, + chain: Some(value.chain_update), + } + } +} + +impl From for Update { + fn from(value: SyncResult) -> Self { + Self { + last_active_indices: BTreeMap::new(), + graph: value.graph_update, + chain: Some(value.chain_update), + } + } +} + /// The changes made to a wallet by applying an [`Update`]. #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, Default)] pub struct ChangeSet { @@ -2262,7 +2283,8 @@ impl Wallet { /// transactions related to your wallet into it. /// /// [`commit`]: Self::commit - pub fn apply_update(&mut self, update: Update) -> Result<(), CannotConnectError> { + pub fn apply_update(&mut self, update: impl Into) -> Result<(), CannotConnectError> { + let update = update.into(); let mut changeset = match update.chain { Some(chain_update) => ChangeSet::from(self.chain.apply_update(chain_update)?), None => ChangeSet::default(), @@ -2387,6 +2409,31 @@ impl Wallet { } } +/// Methods to construct sync/full-scan requests for spk-based chain sources. +impl Wallet { + /// Create a partial [`SyncRequest`] for this wallet for all revealed spks. + /// + /// This is the first step when performing a spk-based wallet partial sync, the returned + /// [`SyncRequest`] collects all revealed script pubkeys from the wallet keychain needed to + /// start a blockchain sync with a spk based blockchain client. + pub fn start_sync_with_revealed_spks(&self) -> SyncRequest { + SyncRequest::from_chain_tip(self.chain.tip()) + .populate_with_revealed_spks(&self.indexed_graph.index, ..) + } + + /// 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 needed to + /// start a blockchain full scan with a spk based 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 start_full_scan(&self) -> FullScanRequest { + FullScanRequest::from_keychain_txout_index(self.chain.tip(), &self.indexed_graph.index) + } +} + impl AsRef> for Wallet { fn as_ref(&self) -> &bdk_chain::tx_graph::TxGraph { self.indexed_graph.graph()