]> Untitled Git - bdk/commitdiff
Add SyncOptions as the second argument to Wallet::sync
authorLLFourn <lloyd.fourn@gmail.com>
Thu, 27 Jan 2022 05:52:53 +0000 (16:52 +1100)
committerLLFourn <lloyd.fourn@gmail.com>
Thu, 24 Feb 2022 09:39:00 +0000 (20:39 +1100)
The current options are awkward and it would be good if we could
introduce more in the future without breaking changes.

13 files changed:
CHANGELOG.md
README.md
examples/compact_filters_balance.rs
src/blockchain/any.rs
src/blockchain/compact_filters/mod.rs
src/blockchain/electrum.rs
src/blockchain/esplora/reqwest.rs
src/blockchain/esplora/ureq.rs
src/blockchain/mod.rs
src/blockchain/rpc.rs
src/lib.rs
src/testutils/blockchain_tests.rs
src/wallet/mod.rs

index 73a1bfe0392be2d0389ee500e8431f27aa90bde9..319fb628850d7fdc334deb2782a51ded244e794b 100644 (file)
@@ -8,10 +8,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 - Removed default verification from `wallet::sync`. sync-time verification is added in `script_sync` and is activated by `verify` feature flag.
 - `verify` flag removed from `TransactionDetails`.
-- Removed Blockchain from Wallet.
-- Removed `Wallet::broadcast` (just use blockchain.broadcast)
+
+### Sync API change
+
+To decouple the `Wallet` from the `Blockchain` we've made major changes:
+
+- Removed `Blockchain` from Wallet.
+- Removed `Wallet::broadcast` (just use `Blockchain::broadcast`)
 - Depreciated `Wallet::new_offline` (all wallets are offline now)
-- Changed `Wallet::sync` to take a blockchain argument.
+- Changed `Wallet::sync` to take a `Blockchain`.
+- Stop making a request for the block height when calling `Wallet:new`.
+- Added `SyncOptions` to capture extra (future) arguments to `Wallet::sync`.
 
 ## [v0.16.1] - [v0.16.0]
 
index af449ac0b16695af5acec5d00fa4bf8c5dda0ecc..8f2c7e74959ec47ef8e6a127f287b9f42af4c642 100644 (file)
--- a/README.md
+++ b/README.md
@@ -41,21 +41,21 @@ The `bdk` library aims to be the core building block for Bitcoin wallets of any
 ```rust,no_run
 use bdk::Wallet;
 use bdk::database::MemoryDatabase;
-use bdk::blockchain::{noop_progress, ElectrumBlockchain};
+use bdk::blockchain::ElectrumBlockchain;
+use bdk::SyncOptions;
 
 use bdk::electrum_client::Client;
 
 fn main() -> Result<(), bdk::Error> {
-    let client = Client::new("ssl://electrum.blockstream.info:60002")?;
+    let blockchain = ElectrumBlockchain::from(Client::new("ssl://electrum.blockstream.info:60002")?);
     let wallet = Wallet::new(
         "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
         Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
         bitcoin::Network::Testnet,
         MemoryDatabase::default(),
-        ElectrumBlockchain::from(client)
     )?;
 
-    wallet.sync(noop_progress(), None)?;
+    wallet.sync(&blockchain, SyncOptions::default())?;
 
     println!("Descriptor balance: {} SAT", wallet.get_balance()?);
 
@@ -88,9 +88,9 @@ fn main() -> Result<(), bdk::Error> {
 ### Create a transaction
 
 ```rust,no_run
-use bdk::{FeeRate, Wallet};
+use bdk::{FeeRate, Wallet, SyncOptions};
 use bdk::database::MemoryDatabase;
-use bdk::blockchain::{noop_progress, ElectrumBlockchain};
+use bdk::blockchain::ElectrumBlockchain;
 
 use bdk::electrum_client::Client;
 use bdk::wallet::AddressIndex::New;
@@ -98,16 +98,15 @@ use bdk::wallet::AddressIndex::New;
 use bitcoin::consensus::serialize;
 
 fn main() -> Result<(), bdk::Error> {
-    let client = Client::new("ssl://electrum.blockstream.info:60002")?;
+    let blockchain = ElectrumBlockchain::from(Client::new("ssl://electrum.blockstream.info:60002")?);
     let wallet = Wallet::new(
         "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
         Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
         bitcoin::Network::Testnet,
         MemoryDatabase::default(),
-        ElectrumBlockchain::from(client)
     )?;
 
-    wallet.sync(noop_progress(), None)?;
+    wallet.sync(&blockchain, SyncOptions::default())?;
 
     let send_to = wallet.get_address(New)?;
     let (psbt, details) = {
index 2154de4f143dd6e5219bfce0acad99e3e3a87a56..ce875b4d597d095baf1c32d34cdddbde1d706301 100644 (file)
@@ -10,7 +10,6 @@
 // licenses.
 
 use bdk::blockchain::compact_filters::*;
-use bdk::blockchain::noop_progress;
 use bdk::database::MemoryDatabase;
 use bdk::*;
 use bitcoin::*;
@@ -36,7 +35,7 @@ fn main() -> Result<(), CompactFiltersError> {
 
     let database = MemoryDatabase::default();
     let wallet = Arc::new(Wallet::new(descriptor, None, Network::Testnet, database).unwrap());
-    wallet.sync(&blockchain, noop_progress(), None).unwrap();
+    wallet.sync(&blockchain, SyncOptions::default()).unwrap();
     info!("balance: {}", wallet.get_balance()?);
     Ok(())
 }
index 4ff9459fc8d4fa36c3e835e65224ffb6e39a70b2..ef4abffacb1c3e948b1c0d48a9f8249e3ba0a8a0 100644 (file)
@@ -110,10 +110,10 @@ impl GetHeight for AnyBlockchain {
 
 #[maybe_async]
 impl WalletSync for AnyBlockchain {
-    fn wallet_sync<D: BatchDatabase, P: Progress>(
+    fn wallet_sync<D: BatchDatabase>(
         &self,
         database: &mut D,
-        progress_update: P,
+        progress_update: Box<dyn Progress>,
     ) -> Result<(), Error> {
         maybe_await!(impl_inner_method!(
             self,
@@ -123,10 +123,10 @@ impl WalletSync for AnyBlockchain {
         ))
     }
 
-    fn wallet_setup<D: BatchDatabase, P: Progress>(
+    fn wallet_setup<D: BatchDatabase>(
         &self,
         database: &mut D,
-        progress_update: P,
+        progress_update: Box<dyn Progress>,
     ) -> Result<(), Error> {
         maybe_await!(impl_inner_method!(
             self,
index 1fd99fc3ef6f5828d37acb606f4b85b15a589ee8..d0b96421ab2e78eb509848f550e33c4e8a749046 100644 (file)
@@ -251,10 +251,10 @@ impl GetHeight for CompactFiltersBlockchain {
 
 impl WalletSync for CompactFiltersBlockchain {
     #[allow(clippy::mutex_atomic)] // Mutex is easier to understand than a CAS loop.
-    fn wallet_setup<D: BatchDatabase, P: Progress>(
+    fn wallet_setup<D: BatchDatabase>(
         &self,
         database: &mut D,
-        progress_update: P,
+        progress_update: Box<dyn Progress>,
     ) -> Result<(), Error> {
         let first_peer = &self.peers[0];
 
index 40efdd5595a8efad45e1471e95fd5d45603533e6..b10b90d508cbad4643db7996a4aafde322004f2c 100644 (file)
@@ -95,10 +95,10 @@ impl GetHeight for ElectrumBlockchain {
 }
 
 impl WalletSync for ElectrumBlockchain {
-    fn wallet_setup<D: BatchDatabase, P: Progress>(
+    fn wallet_setup<D: BatchDatabase>(
         &self,
         database: &mut D,
-        _progress_update: P,
+        _progress_update: Box<dyn Progress>,
     ) -> Result<(), Error> {
         let mut request = script_sync::start(database, self.stop_gap)?;
         let mut block_times = HashMap::<u32, u32>::new();
index d64bf5631847ed416ed4a58f4621494dda2047ad..0a9ed4dd397f5e6d8033fb28f136a558667e463f 100644 (file)
@@ -114,10 +114,10 @@ impl GetHeight for EsploraBlockchain {
 
 #[maybe_async]
 impl WalletSync for EsploraBlockchain {
-    fn wallet_setup<D: BatchDatabase, P: Progress>(
+    fn wallet_setup<D: BatchDatabase>(
         &self,
         database: &mut D,
-        _progress_update: P,
+        _progress_update: Box<dyn Progress>,
     ) -> Result<(), Error> {
         use crate::blockchain::script_sync::Request;
         let mut request = script_sync::start(database, self.stop_gap)?;
index ad0dd77332b4fad0686c8f77559e1c83eb7a0fd6..3e240f43fd75efe5173eb0722c538f29367ed9b3 100644 (file)
@@ -109,10 +109,10 @@ impl GetHeight for EsploraBlockchain {
 }
 
 impl WalletSync for EsploraBlockchain {
-    fn wallet_setup<D: BatchDatabase, P: Progress>(
+    fn wallet_setup<D: BatchDatabase>(
         &self,
         database: &mut D,
-        _progress_update: P,
+        _progress_update: Box<dyn Progress>,
     ) -> Result<(), Error> {
         use crate::blockchain::script_sync::Request;
         let mut request = script_sync::start(database, self.stop_gap)?;
index 8f3e2523688eee0ab6dd7c1036cf4995308879d8..5962fca253d5c218bdb594b93145d53710c2ca6d 100644 (file)
@@ -118,10 +118,10 @@ pub trait WalletSync {
     /// For types that do not have that distinction, only this method can be implemented, since
     /// [`WalletSync::wallet_sync`] defaults to calling this internally if not overridden.
     /// Populate the internal database with transactions and UTXOs
-    fn wallet_setup<D: BatchDatabase, P: Progress>(
+    fn wallet_setup<D: BatchDatabase>(
         &self,
         database: &mut D,
-        progress_update: P,
+        progress_update: Box<dyn Progress>,
     ) -> Result<(), Error>;
 
     /// If not overridden, it defaults to calling [`Self::wallet_setup`] internally.
@@ -141,10 +141,10 @@ pub trait WalletSync {
     /// [`BatchOperations::set_tx`]: crate::database::BatchOperations::set_tx
     /// [`BatchOperations::set_utxo`]: crate::database::BatchOperations::set_utxo
     /// [`BatchOperations::del_utxo`]: crate::database::BatchOperations::del_utxo
-    fn wallet_sync<D: BatchDatabase, P: Progress>(
+    fn wallet_sync<D: BatchDatabase>(
         &self,
         database: &mut D,
-        progress_update: P,
+        progress_update: Box<dyn Progress>,
     ) -> Result<(), Error> {
         maybe_await!(self.wallet_setup(database, progress_update))
     }
@@ -164,7 +164,7 @@ pub type ProgressData = (f32, Option<String>);
 
 /// Trait for types that can receive and process progress updates during [`WalletSync::wallet_sync`] and
 /// [`WalletSync::wallet_setup`]
-pub trait Progress: Send + 'static {
+pub trait Progress: Send + 'static + core::fmt::Debug {
     /// Send a new progress update
     ///
     /// The `progress` value should be in the range 0.0 - 100.0, and the `message` value is an
@@ -189,7 +189,7 @@ impl Progress for Sender<ProgressData> {
 }
 
 /// Type that implements [`Progress`] and drops every update received
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default, Debug)]
 pub struct NoopProgress;
 
 /// Create a new instance of [`NoopProgress`]
@@ -204,7 +204,7 @@ impl Progress for NoopProgress {
 }
 
 /// Type that implements [`Progress`] and logs at level `INFO` every update received
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Default, Debug)]
 pub struct LogProgress;
 
 /// Create a new instance of [`LogProgress`]
@@ -251,18 +251,18 @@ impl<T: GetHeight> GetHeight for Arc<T> {
 
 #[maybe_async]
 impl<T: WalletSync> WalletSync for Arc<T> {
-    fn wallet_setup<D: BatchDatabase, P: Progress>(
+    fn wallet_setup<D: BatchDatabase>(
         &self,
         database: &mut D,
-        progress_update: P,
+        progress_update: Box<dyn Progress>,
     ) -> Result<(), Error> {
         maybe_await!(self.deref().wallet_setup(database, progress_update))
     }
 
-    fn wallet_sync<D: BatchDatabase, P: Progress>(
+    fn wallet_sync<D: BatchDatabase>(
         &self,
         database: &mut D,
-        progress_update: P,
+        progress_update: Box<dyn Progress>,
     ) -> Result<(), Error> {
         maybe_await!(self.deref().wallet_sync(database, progress_update))
     }
index 403f0bbd15de8cca30519f30d4da2f81123d4bce..b96af9937826ec36420fb0a52af2170e792dc8b7 100644 (file)
@@ -168,10 +168,10 @@ impl GetHeight for RpcBlockchain {
 }
 
 impl WalletSync for RpcBlockchain {
-    fn wallet_setup<D: BatchDatabase, P: Progress>(
+    fn wallet_setup<D: BatchDatabase>(
         &self,
         database: &mut D,
-        progress_update: P,
+        progress_update: Box<dyn Progress>,
     ) -> Result<(), Error> {
         let mut scripts_pubkeys = database.iter_script_pubkeys(Some(KeychainKind::External))?;
         scripts_pubkeys.extend(database.iter_script_pubkeys(Some(KeychainKind::Internal))?);
@@ -219,10 +219,10 @@ impl WalletSync for RpcBlockchain {
         self.wallet_sync(database, progress_update)
     }
 
-    fn wallet_sync<D: BatchDatabase, P: Progress>(
+    fn wallet_sync<D: BatchDatabase>(
         &self,
         db: &mut D,
-        _progress_update: P,
+        _progress_update: Box<dyn Progress>,
     ) -> Result<(), Error> {
         let mut indexes = HashMap::new();
         for keykind in &[KeychainKind::External, KeychainKind::Internal] {
index b998d36aca3cb65d0c0b5f75be3f21e97ff50585..4b8a222840b070e4dec3d6fe440e7b163e12b8b5 100644 (file)
@@ -53,9 +53,9 @@
 
 ### Example
 ```no_run
-use bdk::Wallet;
+use bdk::{Wallet, SyncOptions};
 use bdk::database::MemoryDatabase;
-use bdk::blockchain::{noop_progress, ElectrumBlockchain};
+use bdk::blockchain::ElectrumBlockchain;
 use bdk::electrum_client::Client;
 
 fn main() -> Result<(), bdk::Error> {
@@ -68,7 +68,7 @@ fn main() -> Result<(), bdk::Error> {
         MemoryDatabase::default(),
     )?;
 
-    wallet.sync(&blockchain, noop_progress(), None)?;
+    wallet.sync(&blockchain, SyncOptions::default())?;
 
     println!("Descriptor balance: {} SAT", wallet.get_balance()?);
 
@@ -108,9 +108,9 @@ fn main() -> Result<(), bdk::Error> {
 
 ### Example
 ```no_run
-use bdk::{FeeRate, Wallet};
+use bdk::{FeeRate, Wallet, SyncOptions};
 use bdk::database::MemoryDatabase;
-use bdk::blockchain::{noop_progress, ElectrumBlockchain};
+use bdk::blockchain::ElectrumBlockchain;
 use bdk::electrum_client::Client;
 
 use bitcoin::consensus::serialize;
@@ -126,7 +126,7 @@ fn main() -> Result<(), bdk::Error> {
     )?;
     let blockchain = ElectrumBlockchain::from(client);
 
-    wallet.sync(&blockchain, noop_progress(), None)?;
+    wallet.sync(&blockchain, SyncOptions::default())?;
 
     let send_to = wallet.get_address(New)?;
     let (psbt, details) = {
@@ -272,6 +272,7 @@ pub use wallet::address_validator;
 pub use wallet::signer;
 pub use wallet::signer::SignOptions;
 pub use wallet::tx_builder::TxBuilder;
+pub use wallet::SyncOptions;
 pub use wallet::Wallet;
 
 /// Get the version of BDK at runtime
index cf6be5a7086d6e7f7cd0f4fa8e50abd1e1e1275d..68858a84108e56c32a7045ab72c2ca2fe37bfd25 100644 (file)
@@ -361,10 +361,10 @@ macro_rules! bdk_blockchain_tests {
         mod bdk_blockchain_tests {
             use $crate::bitcoin::{Transaction, Network};
             use $crate::testutils::blockchain_tests::TestClient;
-            use $crate::blockchain::{Blockchain, noop_progress};
+            use $crate::blockchain::Blockchain;
             use $crate::database::MemoryDatabase;
             use $crate::types::KeychainKind;
-            use $crate::{Wallet, FeeRate};
+            use $crate::{Wallet, FeeRate, SyncOptions};
             use $crate::testutils;
 
             use super::*;
@@ -392,7 +392,7 @@ macro_rules! bdk_blockchain_tests {
 
                 // rpc need to call import_multi before receiving any tx, otherwise will not see tx in the mempool
                 #[cfg(feature = "test-rpc")]
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
 
                 (wallet, blockchain, descriptors, test_client)
             }
@@ -415,7 +415,7 @@ macro_rules! bdk_blockchain_tests {
                 #[cfg(not(feature = "test-rpc"))]
                 assert!(wallet.database().deref().get_sync_time().unwrap().is_none(), "initial sync_time not none");
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert!(wallet.database().deref().get_sync_time().unwrap().is_some(), "sync_time hasn't been updated");
 
                 assert_eq!(wallet.get_balance().unwrap(), 50_000, "incorrect balance");
@@ -439,7 +439,7 @@ macro_rules! bdk_blockchain_tests {
                     @tx ( (@external descriptors, 25) => 50_000 )
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
 
                 assert_eq!(wallet.get_balance().unwrap(), 100_000, "incorrect balance");
                 assert_eq!(wallet.list_transactions(false).unwrap().len(), 2, "incorrect number of txs");
@@ -449,14 +449,14 @@ macro_rules! bdk_blockchain_tests {
             fn test_sync_before_and_after_receive() {
                 let (wallet, blockchain, descriptors, mut test_client) = init_single_sig();
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 0);
 
                 test_client.receive(testutils! {
                     @tx ( (@external descriptors, 0) => 50_000 )
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
 
                 assert_eq!(wallet.get_balance().unwrap(), 50_000, "incorrect balance");
                 assert_eq!(wallet.list_transactions(false).unwrap().len(), 1, "incorrect number of txs");
@@ -470,7 +470,7 @@ macro_rules! bdk_blockchain_tests {
                     @tx ( (@external descriptors, 0) => 50_000, (@external descriptors, 1) => 25_000, (@external descriptors, 5) => 30_000 )
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
 
                 assert_eq!(wallet.get_balance().unwrap(), 105_000, "incorrect balance");
                 assert_eq!(wallet.list_transactions(false).unwrap().len(), 1, "incorrect number of txs");
@@ -494,7 +494,7 @@ macro_rules! bdk_blockchain_tests {
                     @tx ( (@external descriptors, 5) => 25_000 )
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
 
                 assert_eq!(wallet.get_balance().unwrap(), 75_000, "incorrect balance");
                 assert_eq!(wallet.list_transactions(false).unwrap().len(), 2, "incorrect number of txs");
@@ -509,14 +509,14 @@ macro_rules! bdk_blockchain_tests {
                     @tx ( (@external descriptors, 0) => 50_000 )
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 50_000);
 
                 test_client.receive(testutils! {
                     @tx ( (@external descriptors, 0) => 25_000 )
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 75_000, "incorrect balance");
             }
 
@@ -528,7 +528,7 @@ macro_rules! bdk_blockchain_tests {
                     @tx ( (@external descriptors, 0) => 50_000 ) ( @replaceable true )
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
 
                 assert_eq!(wallet.get_balance().unwrap(), 50_000, "incorrect balance");
                 assert_eq!(wallet.list_transactions(false).unwrap().len(), 1, "incorrect number of txs");
@@ -542,7 +542,7 @@ macro_rules! bdk_blockchain_tests {
 
                 let new_txid = test_client.bump_fee(&txid);
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
 
                 assert_eq!(wallet.get_balance().unwrap(), 50_000, "incorrect balance after bump");
                 assert_eq!(wallet.list_transactions(false).unwrap().len(), 1, "incorrect number of txs after bump");
@@ -566,7 +566,7 @@ macro_rules! bdk_blockchain_tests {
                     @tx ( (@external descriptors, 0) => 50_000 ) ( @confirmations 1 ) ( @replaceable true )
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
 
                 assert_eq!(wallet.get_balance().unwrap(), 50_000, "incorrect balance");
                 assert_eq!(wallet.list_transactions(false).unwrap().len(), 1, "incorrect number of txs");
@@ -579,7 +579,7 @@ macro_rules! bdk_blockchain_tests {
                 // Invalidate 1 block
                 test_client.invalidate(1);
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
 
                 assert_eq!(wallet.get_balance().unwrap(), 50_000, "incorrect balance after invalidate");
 
@@ -598,7 +598,7 @@ macro_rules! bdk_blockchain_tests {
                     @tx ( (@external descriptors, 0) => 50_000 )
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 50_000, "incorrect balance");
 
                 let mut builder = wallet.build_tx();
@@ -609,7 +609,7 @@ macro_rules! bdk_blockchain_tests {
                 let tx = psbt.extract_tx();
                 println!("{}", bitcoin::consensus::encode::serialize_hex(&tx));
                 blockchain.broadcast(&tx).unwrap();
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), details.received, "incorrect balance after send");
 
                 assert_eq!(wallet.list_transactions(false).unwrap().len(), 2, "incorrect number of txs");
@@ -623,13 +623,13 @@ macro_rules! bdk_blockchain_tests {
                 let (wallet, blockchain, descriptors, mut test_client) = init_single_sig();
                                 let receiver_wallet = get_wallet_from_descriptors(&("wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)".to_string(), None));
                 // need to sync so rpc can start watching
-                receiver_wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                receiver_wallet.sync(&blockchain, SyncOptions::default()).unwrap();
 
                 test_client.receive(testutils! {
                     @tx ( (@external descriptors, 0) => 50_000, (@external descriptors, 1) => 25_000 ) (@confirmations 1)
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 75_000, "incorrect balance");
                 let target_addr = receiver_wallet.get_address($crate::wallet::AddressIndex::New).unwrap().address;
 
@@ -654,7 +654,7 @@ macro_rules! bdk_blockchain_tests {
                 blockchain.broadcast(&tx1).unwrap();
                 blockchain.broadcast(&tx2).unwrap();
 
-                receiver_wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                receiver_wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(receiver_wallet.get_balance().unwrap(), 49_000, "should have received coins once and only once");
             }
 
@@ -679,7 +679,7 @@ macro_rules! bdk_blockchain_tests {
                     });
                 }
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
 
                 assert_eq!(wallet.get_balance().unwrap(), 100_000);
             }
@@ -694,7 +694,7 @@ macro_rules! bdk_blockchain_tests {
                     @tx ( (@external descriptors, 0) => 50_000 )
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 50_000, "incorrect balance");
 
                 let tx_map = wallet.list_transactions(false).unwrap().into_iter().map(|tx| (tx.txid, tx)).collect::<std::collections::HashMap<_, _>>();
@@ -702,7 +702,7 @@ macro_rules! bdk_blockchain_tests {
                 assert!(details.confirmation_time.is_none());
 
                 test_client.generate(1, Some(node_addr));
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
 
                 let tx_map = wallet.list_transactions(false).unwrap().into_iter().map(|tx| (tx.txid, tx)).collect::<std::collections::HashMap<_, _>>();
                 let details = tx_map.get(&received_txid).unwrap();
@@ -718,7 +718,7 @@ macro_rules! bdk_blockchain_tests {
                     @tx ( (@external descriptors, 0) => 50_000 )
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 50_000, "incorrect balance");
 
                 let mut builder = wallet.build_tx();
@@ -730,7 +730,7 @@ macro_rules! bdk_blockchain_tests {
                 let sent_tx = psbt.extract_tx();
                 blockchain.broadcast(&sent_tx).unwrap();
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), details.received, "incorrect balance after receive");
 
                 // empty wallet
@@ -739,7 +739,7 @@ macro_rules! bdk_blockchain_tests {
                 #[cfg(feature = "rpc")]  // rpc cannot see mempool tx before importmulti
                 test_client.generate(1, Some(node_addr));
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 let tx_map = wallet.list_transactions(false).unwrap().into_iter().map(|tx| (tx.txid, tx)).collect::<std::collections::HashMap<_, _>>();
 
                 let received = tx_map.get(&received_txid).unwrap();
@@ -761,7 +761,7 @@ macro_rules! bdk_blockchain_tests {
                     @tx ( (@external descriptors, 0) => 50_000 )
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 50_000, "incorrect balance");
 
                 let mut total_sent = 0;
@@ -773,12 +773,12 @@ macro_rules! bdk_blockchain_tests {
                     assert!(finalized, "Cannot finalize transaction");
                     blockchain.broadcast(&psbt.extract_tx()).unwrap();
 
-                    wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                    wallet.sync(&blockchain, SyncOptions::default()).unwrap();
 
                     total_sent += 5_000 + details.fee.unwrap_or(0);
                 }
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 50_000 - total_sent, "incorrect balance after chain");
 
                 // empty wallet
@@ -788,7 +788,7 @@ macro_rules! bdk_blockchain_tests {
                 #[cfg(feature = "rpc")]  // rpc cannot see mempool tx before importmulti
                 test_client.generate(1, Some(node_addr));
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 50_000 - total_sent, "incorrect balance empty wallet");
 
             }
@@ -802,7 +802,7 @@ macro_rules! bdk_blockchain_tests {
                     @tx ( (@external descriptors, 0) => 50_000 ) (@confirmations 1)
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 50_000, "incorrect balance");
 
                 let mut builder = wallet.build_tx();
@@ -811,7 +811,7 @@ macro_rules! bdk_blockchain_tests {
                 let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
                 assert!(finalized, "Cannot finalize transaction");
                 blockchain.broadcast(&psbt.extract_tx()).unwrap();
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 50_000 - details.fee.unwrap_or(0) - 5_000, "incorrect balance from fees");
                 assert_eq!(wallet.get_balance().unwrap(), details.received, "incorrect balance from received");
 
@@ -821,7 +821,7 @@ macro_rules! bdk_blockchain_tests {
                 let finalized = wallet.sign(&mut new_psbt, Default::default()).unwrap();
                 assert!(finalized, "Cannot finalize transaction");
                 blockchain.broadcast(&new_psbt.extract_tx()).unwrap();
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 50_000 - new_details.fee.unwrap_or(0) - 5_000, "incorrect balance from fees after bump");
                 assert_eq!(wallet.get_balance().unwrap(), new_details.received, "incorrect balance from received after bump");
 
@@ -837,7 +837,7 @@ macro_rules! bdk_blockchain_tests {
                     @tx ( (@external descriptors, 0) => 50_000 ) (@confirmations 1)
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 50_000, "incorrect balance");
 
                 let mut builder = wallet.build_tx();
@@ -846,7 +846,7 @@ macro_rules! bdk_blockchain_tests {
                 let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
                 assert!(finalized, "Cannot finalize transaction");
                 blockchain.broadcast(&psbt.extract_tx()).unwrap();
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 1_000 - details.fee.unwrap_or(0), "incorrect balance after send");
                 assert_eq!(wallet.get_balance().unwrap(), details.received, "incorrect received after send");
 
@@ -856,7 +856,7 @@ macro_rules! bdk_blockchain_tests {
                 let finalized = wallet.sign(&mut new_psbt, Default::default()).unwrap();
                 assert!(finalized, "Cannot finalize transaction");
                 blockchain.broadcast(&new_psbt.extract_tx()).unwrap();
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 0, "incorrect balance after change removal");
                 assert_eq!(new_details.received, 0, "incorrect received after change removal");
 
@@ -872,7 +872,7 @@ macro_rules! bdk_blockchain_tests {
                     @tx ( (@external descriptors, 0) => 50_000, (@external descriptors, 1) => 25_000 ) (@confirmations 1)
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 75_000, "incorrect balance");
 
                 let mut builder = wallet.build_tx();
@@ -881,7 +881,7 @@ macro_rules! bdk_blockchain_tests {
                 let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
                 assert!(finalized, "Cannot finalize transaction");
                 blockchain.broadcast(&psbt.extract_tx()).unwrap();
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 26_000 - details.fee.unwrap_or(0), "incorrect balance after send");
                 assert_eq!(details.received, 1_000 - details.fee.unwrap_or(0), "incorrect received after send");
 
@@ -891,7 +891,7 @@ macro_rules! bdk_blockchain_tests {
                 let finalized = wallet.sign(&mut new_psbt, Default::default()).unwrap();
                 assert!(finalized, "Cannot finalize transaction");
                 blockchain.broadcast(&new_psbt.extract_tx()).unwrap();
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(new_details.sent, 75_000, "incorrect sent");
                 assert_eq!(wallet.get_balance().unwrap(), new_details.received, "incorrect balance after add input");
             }
@@ -905,7 +905,7 @@ macro_rules! bdk_blockchain_tests {
                     @tx ( (@external descriptors, 0) => 50_000, (@external descriptors, 1) => 25_000 ) (@confirmations 1)
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 75_000, "incorrect balance");
 
                 let mut builder = wallet.build_tx();
@@ -914,7 +914,7 @@ macro_rules! bdk_blockchain_tests {
                 let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
                 assert!(finalized, "Cannot finalize transaction");
                 blockchain.broadcast(&psbt.extract_tx()).unwrap();
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 26_000 - details.fee.unwrap_or(0), "incorrect balance after send");
                 assert_eq!(details.received, 1_000 - details.fee.unwrap_or(0), "incorrect received after send");
 
@@ -926,7 +926,7 @@ macro_rules! bdk_blockchain_tests {
                 let finalized = wallet.sign(&mut new_psbt, Default::default()).unwrap();
                 assert!(finalized, "Cannot finalize transaction");
                 blockchain.broadcast(&new_psbt.extract_tx()).unwrap();
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(new_details.sent, 75_000, "incorrect sent");
                 assert_eq!(wallet.get_balance().unwrap(), 0, "incorrect balance after add input");
                 assert_eq!(new_details.received, 0, "incorrect received after add input");
@@ -941,7 +941,7 @@ macro_rules! bdk_blockchain_tests {
                     @tx ( (@external descriptors, 0) => 50_000 )
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 50_000, "incorrect balance");
 
                 let mut builder = wallet.build_tx();
@@ -956,7 +956,7 @@ macro_rules! bdk_blockchain_tests {
                 assert!(serialized_tx.windows(data.len()).any(|e| e==data), "cannot find op_return data in transaction");
                 blockchain.broadcast(&tx).unwrap();
                 test_client.generate(1, Some(node_addr));
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 50_000 - details.fee.unwrap_or(0), "incorrect balance after send");
 
                 let tx_map = wallet.list_transactions(false).unwrap().into_iter().map(|tx| (tx.txid, tx)).collect::<std::collections::HashMap<_, _>>();
@@ -969,7 +969,7 @@ macro_rules! bdk_blockchain_tests {
 
                 let wallet_addr = wallet.get_address($crate::wallet::AddressIndex::New).unwrap().address;
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 0, "incorrect balance");
 
                 test_client.generate(1, Some(wallet_addr));
@@ -982,7 +982,7 @@ macro_rules! bdk_blockchain_tests {
                 }
 
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert!(wallet.get_balance().unwrap() > 0, "incorrect balance after receiving coinbase");
             }
 
@@ -1058,7 +1058,7 @@ macro_rules! bdk_blockchain_tests {
                     @tx ( (@external descriptors, 0) => 50_000 )
                 });
 
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), 50_000, "wallet has incorrect balance");
 
                 // 4. Send 25_000 sats from test BDK wallet to test bitcoind node taproot wallet
@@ -1070,7 +1070,7 @@ macro_rules! bdk_blockchain_tests {
                 assert!(finalized, "wallet cannot finalize transaction");
                 let tx = psbt.extract_tx();
                 blockchain.broadcast(&tx).unwrap();
-                wallet.sync(&blockchain, noop_progress(), None).unwrap();
+                wallet.sync(&blockchain, SyncOptions::default()).unwrap();
                 assert_eq!(wallet.get_balance().unwrap(), details.received, "wallet has incorrect balance after send");
                 assert_eq!(wallet.list_transactions(false).unwrap().len(), 2, "wallet has incorrect number of txs");
                 assert_eq!(wallet.list_unspent().unwrap().len(), 1, "wallet has incorrect number of unspents");
index 9effd1c0b9e53f3b4b5fc3dd08001387eb4bcf0d..a8d6a62c8aa8707c03ae072314721957f2842c9f 100644 (file)
@@ -55,7 +55,7 @@ use signer::{SignOptions, Signer, SignerOrdering, SignersContainer};
 use tx_builder::{BumpFee, CreateTx, FeePolicy, TxBuilder, TxParams};
 use utils::{check_nlocktime, check_nsequence_rbf, After, Older, SecpCtx};
 
-use crate::blockchain::{GetHeight, Progress, WalletSync};
+use crate::blockchain::{GetHeight, NoopProgress, Progress, WalletSync};
 use crate::database::memory::MemoryDatabase;
 use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils, SyncTime};
 use crate::descriptor::derived::AsDerived;
@@ -156,6 +156,17 @@ impl fmt::Display for AddressInfo {
     }
 }
 
+#[derive(Debug, Default)]
+/// Options to a [`sync`].
+///
+/// [`sync`]: Wallet::sync
+pub struct SyncOptions {
+    /// The progress tracker which may be informed when progress is made.
+    pub progress: Option<Box<dyn Progress>>,
+    /// The maximum number of addresses sync on.
+    pub max_addresses: Option<u32>,
+}
+
 impl<D> Wallet<D>
 where
     D: BatchDatabase,
@@ -1431,27 +1442,26 @@ where
     pub fn database(&self) -> impl std::ops::Deref<Target = D> + '_ {
         self.database.borrow()
     }
-}
 
-impl<D> Wallet<D>
-where
-    D: BatchDatabase,
-{
     /// Sync the internal database with the blockchain
     #[maybe_async]
-    pub fn sync<P: 'static + Progress, B: WalletSync + GetHeight>(
+    pub fn sync<B: WalletSync + GetHeight>(
         &self,
         blockchain: &B,
-        progress_update: P,
-        max_address_param: Option<u32>,
+        sync_opts: SyncOptions,
     ) -> Result<(), Error> {
         debug!("Begin sync...");
 
         let mut run_setup = false;
+        let SyncOptions {
+            max_addresses,
+            progress,
+        } = sync_opts;
+        let progress = progress.unwrap_or_else(|| Box::new(NoopProgress));
 
         let max_address = match self.descriptor.is_deriveable() {
             false => 0,
-            true => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
+            true => max_addresses.unwrap_or(CACHE_ADDR_BATCH_SIZE),
         };
         debug!("max_address {}", max_address);
         if self
@@ -1468,7 +1478,7 @@ where
         if let Some(change_descriptor) = &self.change_descriptor {
             let max_address = match change_descriptor.is_deriveable() {
                 false => 0,
-                true => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
+                true => max_addresses.unwrap_or(CACHE_ADDR_BATCH_SIZE),
             };
 
             if self
@@ -1488,12 +1498,10 @@ where
         // TODO: we should sync if generating an address triggers a new batch to be stored
         if run_setup {
             maybe_await!(
-                blockchain.wallet_setup(self.database.borrow_mut().deref_mut(), progress_update,)
+                blockchain.wallet_setup(self.database.borrow_mut().deref_mut(), progress,)
             )?;
         } else {
-            maybe_await!(
-                blockchain.wallet_sync(self.database.borrow_mut().deref_mut(), progress_update,)
-            )?;
+            maybe_await!(blockchain.wallet_sync(self.database.borrow_mut().deref_mut(), progress,))?;
         }
 
         let sync_time = SyncTime {