]> Untitled Git - bdk/commitdiff
feat!: improve wallet building methods
author志宇 <hello@evanlinjin.me>
Thu, 18 Jul 2024 03:04:00 +0000 (03:04 +0000)
committer志宇 <hello@evanlinjin.me>
Thu, 18 Jul 2024 04:16:05 +0000 (04:16 +0000)
Remove returning `Result` for builder methods on `CreateParams` and
`LoadParams`.

15 files changed:
crates/hwi/src/lib.rs
crates/wallet/README.md
crates/wallet/examples/compiler.rs
crates/wallet/src/descriptor/mod.rs
crates/wallet/src/descriptor/template.rs
crates/wallet/src/wallet/export.rs
crates/wallet/src/wallet/mod.rs
crates/wallet/src/wallet/params.rs
crates/wallet/src/wallet/signer.rs
crates/wallet/tests/common.rs
crates/wallet/tests/wallet.rs
example-crates/wallet_electrum/src/main.rs
example-crates/wallet_esplora_async/src/main.rs
example-crates/wallet_esplora_blocking/src/main.rs
example-crates/wallet_rpc/src/main.rs

index 80649112cf0979b4eaad227bcf99025f18b16620..7bb7e4caf74dfc65ea15822d533a01b331c96a04 100644 (file)
@@ -7,7 +7,7 @@
 //! # use bdk_wallet::descriptor::Descriptor;
 //! # use bdk_wallet::signer::SignerOrdering;
 //! # use bdk_hwi::HWISigner;
-//! # use bdk_wallet::{KeychainKind, SignOptions};
+//! # use bdk_wallet::{KeychainKind, SignOptions, Wallet};
 //! # use hwi::HWIClient;
 //! # use std::sync::Arc;
 //! # use std::str::FromStr;
@@ -20,8 +20,7 @@
 //! let first_device = devices.remove(0)?;
 //! let custom_signer = HWISigner::from_device(&first_device, Network::Testnet.into())?;
 //!
-//! # let mut wallet = bdk_wallet::CreateParams::new("", "", Network::Testnet)?
-//! #   .create_wallet_no_persist()?;
+//! # let mut wallet = Wallet::create("", "").network(Network::Testnet).create_wallet_no_persist()?;
 //! #
 //! // Adding the hardware signer to the BDK wallet
 //! wallet.add_signer(
index 423cf2e77584f454d573401401693b1dba0a68f0..9dee46aaa0ecf5eaf753b5bf5777c0ee596cfc93 100644 (file)
@@ -67,7 +67,7 @@ To persist `Wallet` state data use a data store crate that reads and writes [`Ch
 
 <!-- compile_fail because outpoint and txout are fake variables -->
 ```rust,no_run
-use bdk_wallet::{bitcoin::Network, CreateParams, LoadParams, KeychainKind, ChangeSet};
+use bdk_wallet::{bitcoin::Network, KeychainKind, ChangeSet, Wallet};
 
 // Open or create a new file store for wallet data.
 let mut db =
@@ -78,13 +78,17 @@ let mut db =
 let network = Network::Testnet;
 let descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/0/*)";
 let change_descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/1/*)";
-let load_params = LoadParams::with_descriptors(descriptor, change_descriptor, network)
-    .expect("must parse descriptors");
-let create_params = CreateParams::new(descriptor, change_descriptor, network)
-    .expect("must parse descriptors");
-let mut wallet = match load_params.load_wallet(&mut db).expect("wallet") {
+let wallet_opt = Wallet::load()
+    .descriptors(descriptor, change_descriptor)
+    .network(network)
+    .load_wallet(&mut db)
+    .expect("wallet");
+let mut wallet = match wallet_opt {
     Some(wallet) => wallet,
-    None => create_params.create_wallet(&mut db).expect("wallet"),
+    None => Wallet::create(descriptor, change_descriptor)
+        .network(network)
+        .create_wallet(&mut db)
+        .expect("wallet"),
 };
 
 // Get a new address to receive bitcoin.
index 23102d8b913793549fb93b05198eceaa0c6ca136..d3f1391ebefecf7ea9a11b78b13d4c3ae9f7b7c6 100644 (file)
@@ -21,7 +21,7 @@ use bitcoin::Network;
 use miniscript::policy::Concrete;
 use miniscript::Descriptor;
 
-use bdk_wallet::{CreateParams, KeychainKind};
+use bdk_wallet::{KeychainKind, Wallet};
 
 /// Miniscript policy is a high level abstraction of spending conditions. Defined in the
 /// rust-miniscript library here  https://docs.rs/miniscript/7.0.0/miniscript/policy/index.html
@@ -77,7 +77,8 @@ fn main() -> Result<(), Box<dyn Error>> {
     );
 
     // Create a new wallet from descriptors
-    let mut wallet = CreateParams::new(&descriptor, &internal_descriptor, Network::Regtest)?
+    let mut wallet = Wallet::create(descriptor, internal_descriptor)
+        .network(Network::Regtest)
         .create_wallet_no_persist()?;
 
     println!(
index e196c2f86d566ca1fe8b15d52f4cf3c5edfc62c1..477b265e2fac8cb66abf00c4bcec3d1cc8650f88 100644 (file)
@@ -112,6 +112,16 @@ impl IntoWalletDescriptor for &String {
     }
 }
 
+impl IntoWalletDescriptor for String {
+    fn into_wallet_descriptor(
+        self,
+        secp: &SecpCtx,
+        network: Network,
+    ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
+        self.as_str().into_wallet_descriptor(secp, network)
+    }
+}
+
 impl IntoWalletDescriptor for ExtendedDescriptor {
     fn into_wallet_descriptor(
         self,
index a7f726685c885b0c1e3e7dd097090df88510259c..ee9ec9aedbedd3550ef682f91c7b087a8f5ddb23 100644 (file)
@@ -73,7 +73,7 @@ impl<T: DescriptorTemplate> IntoWalletDescriptor for T {
 ///
 /// ```
 /// # use bdk_wallet::bitcoin::{PrivateKey, Network};
-/// # use bdk_wallet::CreateParams;
+/// # use bdk_wallet::Wallet;
 /// # use bdk_wallet::KeychainKind;
 /// use bdk_wallet::template::P2Pkh;
 ///
@@ -81,7 +81,8 @@ impl<T: DescriptorTemplate> IntoWalletDescriptor for T {
 ///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
 /// let key_internal =
 ///     bitcoin::PrivateKey::from_wif("cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW")?;
-/// let mut wallet = CreateParams::new(P2Pkh(key_external), P2Pkh(key_internal), Network::Testnet)?
+/// let mut wallet = Wallet::create(P2Pkh(key_external), P2Pkh(key_internal))
+///     .network(Network::Testnet)
 ///     .create_wallet_no_persist()?;
 ///
 /// assert_eq!(
@@ -92,6 +93,7 @@ impl<T: DescriptorTemplate> IntoWalletDescriptor for T {
 /// );
 /// # Ok::<_, Box<dyn std::error::Error>>(())
 /// ```
+#[derive(Debug, Clone)]
 pub struct P2Pkh<K: IntoDescriptorKey<Legacy>>(pub K);
 
 impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for P2Pkh<K> {
@@ -106,7 +108,7 @@ impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for P2Pkh<K> {
 ///
 /// ```
 /// # use bdk_wallet::bitcoin::{PrivateKey, Network};
-/// # use bdk_wallet::CreateParams;
+/// # use bdk_wallet::Wallet;
 /// # use bdk_wallet::KeychainKind;
 /// use bdk_wallet::template::P2Wpkh_P2Sh;
 ///
@@ -114,12 +116,9 @@ impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for P2Pkh<K> {
 ///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
 /// let key_internal =
 ///     bitcoin::PrivateKey::from_wif("cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW")?;
-/// let mut wallet = CreateParams::new(
-///     P2Wpkh_P2Sh(key_external),
-///     P2Wpkh_P2Sh(key_internal),
-///     Network::Testnet,
-/// )?
-/// .create_wallet_no_persist()?;
+/// let mut wallet = Wallet::create(P2Wpkh_P2Sh(key_external), P2Wpkh_P2Sh(key_internal))
+///     .network(Network::Testnet)
+///     .create_wallet_no_persist()?;
 ///
 /// assert_eq!(
 ///     wallet
@@ -130,6 +129,7 @@ impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for P2Pkh<K> {
 /// # Ok::<_, Box<dyn std::error::Error>>(())
 /// ```
 #[allow(non_camel_case_types)]
+#[derive(Debug, Clone)]
 pub struct P2Wpkh_P2Sh<K: IntoDescriptorKey<Segwitv0>>(pub K);
 
 impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh_P2Sh<K> {
@@ -144,7 +144,7 @@ impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh_P2Sh<K> {
 ///
 /// ```
 /// # use bdk_wallet::bitcoin::{PrivateKey, Network};
-/// # use bdk_wallet::CreateParams;
+/// # use bdk_wallet::Wallet;
 /// # use bdk_wallet::KeychainKind;
 /// use bdk_wallet::template::P2Wpkh;
 ///
@@ -152,9 +152,9 @@ impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh_P2Sh<K> {
 ///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
 /// let key_internal =
 ///     bitcoin::PrivateKey::from_wif("cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW")?;
-/// let mut wallet =
-///     CreateParams::new(P2Wpkh(key_external), P2Wpkh(key_internal), Network::Testnet)?
-///         .create_wallet_no_persist()?;
+/// let mut wallet = Wallet::create(P2Wpkh(key_external), P2Wpkh(key_internal))
+///     .network(Network::Testnet)
+///     .create_wallet_no_persist()?;
 ///
 /// assert_eq!(
 ///     wallet
@@ -164,6 +164,7 @@ impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh_P2Sh<K> {
 /// );
 /// # Ok::<_, Box<dyn std::error::Error>>(())
 /// ```
+#[derive(Debug, Clone)]
 pub struct P2Wpkh<K: IntoDescriptorKey<Segwitv0>>(pub K);
 
 impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh<K> {
@@ -178,7 +179,7 @@ impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh<K> {
 ///
 /// ```
 /// # use bdk_wallet::bitcoin::{PrivateKey, Network};
-/// # use bdk_wallet::CreateParams;
+/// # use bdk_wallet::Wallet;
 /// # use bdk_wallet::KeychainKind;
 /// use bdk_wallet::template::P2TR;
 ///
@@ -186,7 +187,8 @@ impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh<K> {
 ///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
 /// let key_internal =
 ///     bitcoin::PrivateKey::from_wif("cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW")?;
-/// let mut wallet = CreateParams::new(P2TR(key_external), P2TR(key_internal), Network::Testnet)?
+/// let mut wallet = Wallet::create(P2TR(key_external), P2TR(key_internal))
+///     .network(Network::Testnet)
 ///     .create_wallet_no_persist()?;
 ///
 /// assert_eq!(
@@ -197,6 +199,7 @@ impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh<K> {
 /// );
 /// # Ok::<_, Box<dyn std::error::Error>>(())
 /// ```
+#[derive(Debug, Clone)]
 pub struct P2TR<K: IntoDescriptorKey<Tap>>(pub K);
 
 impl<K: IntoDescriptorKey<Tap>> DescriptorTemplate for P2TR<K> {
@@ -213,24 +216,22 @@ impl<K: IntoDescriptorKey<Tap>> DescriptorTemplate for P2TR<K> {
 ///
 /// ## Example
 ///
-/// ```
+/// ```rust
 /// # use std::str::FromStr;
 /// # use bdk_wallet::bitcoin::{PrivateKey, Network};
-/// # use bdk_wallet::{CreateParams, KeychainKind};
+/// # use bdk_wallet::{Wallet, KeychainKind};
 /// use bdk_wallet::template::Bip44;
 ///
 /// let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
-/// let mut wallet = CreateParams::new(
-///     Bip44(key.clone(), KeychainKind::External),
-///     Bip44(key, KeychainKind::Internal),
-///     Network::Testnet,
-/// )?
-/// .create_wallet_no_persist()?;
+/// let mut wallet = Wallet::create(Bip44(key.clone(), KeychainKind::External), Bip44(key, KeychainKind::Internal))
+///     .network(Network::Testnet)
+///     .create_wallet_no_persist()?;
 ///
 /// assert_eq!(wallet.next_unused_address(KeychainKind::External).to_string(), "mmogjc7HJEZkrLqyQYqJmxUqFaC7i4uf89");
 /// assert_eq!(wallet.public_descriptor(KeychainKind::External).to_string(), "pkh([c55b303f/44'/1'/0']tpubDCuorCpzvYS2LCD75BR46KHE8GdDeg1wsAgNZeNr6DaB5gQK1o14uErKwKLuFmeemkQ6N2m3rNgvctdJLyr7nwu2yia7413Hhg8WWE44cgT/0/*)#5wrnv0xt");
 /// # Ok::<_, Box<dyn std::error::Error>>(())
 /// ```
+#[derive(Debug, Clone)]
 pub struct Bip44<K: DerivableKey<Legacy>>(pub K, pub KeychainKind);
 
 impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44<K> {
@@ -253,22 +254,23 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44<K> {
 /// ```
 /// # use std::str::FromStr;
 /// # use bdk_wallet::bitcoin::{PrivateKey, Network};
-/// # use bdk_wallet::{CreateParams, KeychainKind};
+/// # use bdk_wallet::{KeychainKind, Wallet};
 /// use bdk_wallet::template::Bip44Public;
 ///
 /// let key = bitcoin::bip32::Xpub::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
 /// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
-/// let mut wallet = CreateParams::new(
+/// let mut wallet = Wallet::create(
 ///     Bip44Public(key.clone(), fingerprint, KeychainKind::External),
 ///     Bip44Public(key, fingerprint, KeychainKind::Internal),
-///     Network::Testnet,
-/// )?
+///     )
+///     .network(Network::Testnet)
 /// .create_wallet_no_persist()?;
 ///
 /// assert_eq!(wallet.next_unused_address(KeychainKind::External).to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
 /// assert_eq!(wallet.public_descriptor(KeychainKind::External).to_string(), "pkh([c55b303f/44'/1'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)#cfhumdqz");
 /// # Ok::<_, Box<dyn std::error::Error>>(())
 /// ```
+#[derive(Debug, Clone)]
 pub struct Bip44Public<K: DerivableKey<Legacy>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
 
 impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44Public<K> {
@@ -291,21 +293,22 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44Public<K> {
 /// ```
 /// # use std::str::FromStr;
 /// # use bdk_wallet::bitcoin::{PrivateKey, Network};
-/// # use bdk_wallet::{CreateParams, KeychainKind};
+/// # use bdk_wallet::{Wallet, KeychainKind};
 /// use bdk_wallet::template::Bip49;
 ///
 /// let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
-/// let mut wallet = CreateParams::new(
+/// let mut wallet = Wallet::create(
 ///     Bip49(key.clone(), KeychainKind::External),
 ///     Bip49(key, KeychainKind::Internal),
-///     Network::Testnet,
-/// )?
+/// )
+/// .network(Network::Testnet)
 /// .create_wallet_no_persist()?;
 ///
 /// assert_eq!(wallet.next_unused_address(KeychainKind::External).to_string(), "2N4zkWAoGdUv4NXhSsU8DvS5MB36T8nKHEB");
 /// assert_eq!(wallet.public_descriptor(KeychainKind::External).to_string(), "sh(wpkh([c55b303f/49'/1'/0']tpubDDYr4kdnZgjjShzYNjZUZXUUtpXaofdkMaipyS8ThEh45qFmhT4hKYways7UXmg6V7het1QiFo9kf4kYUXyDvV4rHEyvSpys9pjCB3pukxi/0/*))#s9vxlc8e");
 /// # Ok::<_, Box<dyn std::error::Error>>(())
 /// ```
+#[derive(Debug, Clone)]
 pub struct Bip49<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
 
 impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49<K> {
@@ -328,22 +331,23 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49<K> {
 /// ```
 /// # use std::str::FromStr;
 /// # use bdk_wallet::bitcoin::{PrivateKey, Network};
-/// # use bdk_wallet::{CreateParams, KeychainKind};
+/// # use bdk_wallet::{Wallet, KeychainKind};
 /// use bdk_wallet::template::Bip49Public;
 ///
 /// let key = bitcoin::bip32::Xpub::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
 /// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
-/// let mut wallet = CreateParams::new(
+/// let mut wallet = Wallet::create(
 ///     Bip49Public(key.clone(), fingerprint, KeychainKind::External),
 ///     Bip49Public(key, fingerprint, KeychainKind::Internal),
-///     Network::Testnet,
-/// )?
+/// )
+/// .network(Network::Testnet)
 /// .create_wallet_no_persist()?;
 ///
 /// assert_eq!(wallet.next_unused_address(KeychainKind::External).to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
 /// assert_eq!(wallet.public_descriptor(KeychainKind::External).to_string(), "sh(wpkh([c55b303f/49'/1'/0']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))#3tka9g0q");
 /// # Ok::<_, Box<dyn std::error::Error>>(())
 /// ```
+#[derive(Debug, Clone)]
 pub struct Bip49Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
 
 impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49Public<K> {
@@ -366,21 +370,22 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49Public<K> {
 /// ```
 /// # use std::str::FromStr;
 /// # use bdk_wallet::bitcoin::{PrivateKey, Network};
-/// # use bdk_wallet::{CreateParams, KeychainKind};
+/// # use bdk_wallet::{Wallet, KeychainKind};
 /// use bdk_wallet::template::Bip84;
 ///
 /// let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
-/// let mut wallet = CreateParams::new(
+/// let mut wallet = Wallet::create(
 ///     Bip84(key.clone(), KeychainKind::External),
 ///     Bip84(key, KeychainKind::Internal),
-///     Network::Testnet,
-/// )?
+/// )
+/// .network(Network::Testnet)
 /// .create_wallet_no_persist()?;
 ///
 /// assert_eq!(wallet.next_unused_address(KeychainKind::External).to_string(), "tb1qhl85z42h7r4su5u37rvvw0gk8j2t3n9y7zsg4n");
 /// assert_eq!(wallet.public_descriptor(KeychainKind::External).to_string(), "wpkh([c55b303f/84'/1'/0']tpubDDc5mum24DekpNw92t6fHGp8Gr2JjF9J7i4TZBtN6Vp8xpAULG5CFaKsfugWa5imhrQQUZKXe261asP5koDHo5bs3qNTmf3U3o4v9SaB8gg/0/*)#6kfecsmr");
 /// # Ok::<_, Box<dyn std::error::Error>>(())
 /// ```
+#[derive(Debug, Clone)]
 pub struct Bip84<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
 
 impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84<K> {
@@ -403,21 +408,23 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84<K> {
 /// ```
 /// # use std::str::FromStr;
 /// # use bdk_wallet::bitcoin::{PrivateKey, Network};
-/// # use bdk_wallet::{CreateParams, KeychainKind};
+/// # use bdk_wallet::{Wallet, KeychainKind};
 /// use bdk_wallet::template::Bip84Public;
 ///
 /// let key = bitcoin::bip32::Xpub::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
 /// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
-/// let mut wallet = CreateParams::new(
+/// let mut wallet = Wallet::create(
 ///     Bip84Public(key.clone(), fingerprint, KeychainKind::External),
 ///     Bip84Public(key, fingerprint, KeychainKind::Internal),
-///     Network::Testnet,
-/// )?.create_wallet_no_persist()?;
+/// )
+/// .network(Network::Testnet)
+/// .create_wallet_no_persist()?;
 ///
 /// assert_eq!(wallet.next_unused_address(KeychainKind::External).to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
 /// assert_eq!(wallet.public_descriptor(KeychainKind::External).to_string(), "wpkh([c55b303f/84'/1'/0']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#dhu402yv");
 /// # Ok::<_, Box<dyn std::error::Error>>(())
 /// ```
+#[derive(Debug, Clone)]
 pub struct Bip84Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
 
 impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84Public<K> {
@@ -440,21 +447,22 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84Public<K> {
 /// ```
 /// # use std::str::FromStr;
 /// # use bdk_wallet::bitcoin::{PrivateKey, Network};
-/// # use bdk_wallet::{CreateParams, KeychainKind};
+/// # use bdk_wallet::{Wallet, KeychainKind};
 /// use bdk_wallet::template::Bip86;
 ///
 /// let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
-/// let mut wallet = CreateParams::new(
+/// let mut wallet = Wallet::create(
 ///     Bip86(key.clone(), KeychainKind::External),
 ///     Bip86(key, KeychainKind::Internal),
-///     Network::Testnet,
-/// )?
+/// )
+/// .network(Network::Testnet)
 /// .create_wallet_no_persist()?;
 ///
 /// assert_eq!(wallet.next_unused_address(KeychainKind::External).to_string(), "tb1p5unlj09djx8xsjwe97269kqtxqpwpu2epeskgqjfk4lnf69v4tnqpp35qu");
 /// assert_eq!(wallet.public_descriptor(KeychainKind::External).to_string(), "tr([c55b303f/86'/1'/0']tpubDCiHofpEs47kx358bPdJmTZHmCDqQ8qw32upCSxHrSEdeeBs2T5Mq6QMB2ukeMqhNBiyhosBvJErteVhfURPGXPv3qLJPw5MVpHUewsbP2m/0/*)#dkgvr5hm");
 /// # Ok::<_, Box<dyn std::error::Error>>(())
 /// ```
+#[derive(Debug, Clone)]
 pub struct Bip86<K: DerivableKey<Tap>>(pub K, pub KeychainKind);
 
 impl<K: DerivableKey<Tap>> DescriptorTemplate for Bip86<K> {
@@ -477,22 +485,23 @@ impl<K: DerivableKey<Tap>> DescriptorTemplate for Bip86<K> {
 /// ```
 /// # use std::str::FromStr;
 /// # use bdk_wallet::bitcoin::{PrivateKey, Network};
-/// # use bdk_wallet::{CreateParams, KeychainKind};
+/// # use bdk_wallet::{Wallet, KeychainKind};
 /// use bdk_wallet::template::Bip86Public;
 ///
 /// let key = bitcoin::bip32::Xpub::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
 /// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
-/// let mut wallet = CreateParams::new(
+/// let mut wallet = Wallet::create(
 ///     Bip86Public(key.clone(), fingerprint, KeychainKind::External),
 ///     Bip86Public(key, fingerprint, KeychainKind::Internal),
-///     Network::Testnet,
-/// )?
+/// )
+/// .network(Network::Testnet)
 /// .create_wallet_no_persist()?;
 ///
 /// assert_eq!(wallet.next_unused_address(KeychainKind::External).to_string(), "tb1pwjp9f2k5n0xq73ecuu0c5njvgqr3vkh7yaylmpqvsuuaafymh0msvcmh37");
 /// assert_eq!(wallet.public_descriptor(KeychainKind::External).to_string(), "tr([c55b303f/86'/1'/0']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#2p65srku");
 /// # Ok::<_, Box<dyn std::error::Error>>(())
 /// ```
+#[derive(Debug, Clone)]
 pub struct Bip86Public<K: DerivableKey<Tap>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
 
 impl<K: DerivableKey<Tap>> DescriptorTemplate for Bip86Public<K> {
index 8e4d8a4eea004d488dca228c90e5cf3a26daf012..6dce7503b25b8864f426e8a301e82e481f847c8f 100644 (file)
 //! }"#;
 //!
 //! let import = FullyNodedExport::from_str(import)?;
-//! let wallet = CreateParams::new(
-//!     &import.descriptor(),
-//!     &import.change_descriptor().expect("change descriptor"),
-//!     Network::Testnet,
-//! )?
+//! let wallet = Wallet::create(
+//!     import.descriptor(),
+//!     import.change_descriptor().expect("change descriptor"),
+//! )
+//! .network(Network::Testnet)
 //! .create_wallet_no_persist()?;
 //! # Ok::<_, Box<dyn std::error::Error>>(())
 //! ```
 //! # use bitcoin::*;
 //! # use bdk_wallet::export::*;
 //! # use bdk_wallet::*;
-//! let wallet = CreateParams::new(
+//! let wallet = Wallet::create(
 //!     "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
 //!     "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)",
-//!     Network::Testnet,
-//! )?
+//! )
+//! .network(Network::Testnet)
 //! .create_wallet_no_persist()?;
 //! let export = FullyNodedExport::export_wallet(&wallet, "exported wallet", true).unwrap();
 //!
@@ -221,13 +221,13 @@ mod test {
     use bitcoin::{transaction, BlockHash, Network, Transaction};
 
     use super::*;
-    use crate::wallet::{CreateParams, Wallet};
+    use crate::Wallet;
 
     fn get_test_wallet(descriptor: &str, change_descriptor: &str, network: Network) -> Wallet {
         use crate::wallet::Update;
         use bdk_chain::TxGraph;
-        let mut wallet = CreateParams::new(descriptor, change_descriptor, network)
-            .expect("must parse descriptors")
+        let mut wallet = Wallet::create(descriptor.to_string(), change_descriptor.to_string())
+            .network(network)
             .create_wallet_no_persist()
             .expect("must create wallet");
         let transaction = Transaction {
index 30fcb3c69cf2826baf78d9da6df9e737ff5e2a0b..71468e4e5cd1e1eb840feeeac2d2c89b12d39dc7 100644 (file)
@@ -290,7 +290,8 @@ impl Wallet {
     /// # const EXTERNAL_DESC: &str = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/0/*)";
     /// # const INTERNAL_DESC: &str = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/1/*)";
     /// // Create a non-persisted wallet.
-    /// let wallet = Wallet::create(EXTERNAL_DESC, INTERNAL_DESC, Network::Testnet)?
+    /// let wallet = Wallet::create(EXTERNAL_DESC, INTERNAL_DESC)
+    ///     .network(Network::Testnet)
     ///     .create_wallet_no_persist()?;
     ///
     /// // Create a wallet that is persisted to SQLite database.
@@ -298,48 +299,48 @@ impl Wallet {
     /// # let file_path = temp_dir.path().join("store.db");
     /// use bdk_wallet::rusqlite::Connection;
     /// let mut conn = Connection::open(file_path)?;
-    /// let wallet = Wallet::create(EXTERNAL_DESC, INTERNAL_DESC, Network::Testnet)?
+    /// let wallet = Wallet::create(EXTERNAL_DESC, INTERNAL_DESC)
+    ///     .network(Network::Testnet)
     ///     .create_wallet(&mut conn)?;
     /// # Ok(())
     /// # }
     /// ```
-    pub fn create<E: IntoWalletDescriptor>(
-        descriptor: E,
-        change_descriptor: E,
-        network: Network,
-    ) -> Result<CreateParams, DescriptorError> {
-        CreateParams::new(descriptor, change_descriptor, network)
+    pub fn create<D>(descriptor: D, change_descriptor: D) -> CreateParams
+    where
+        D: IntoWalletDescriptor + Clone + 'static,
+    {
+        CreateParams::new(descriptor, change_descriptor)
     }
 
     /// Create a new [`Wallet`] with given `params`.
     ///
-    /// If you have previously created a wallet, use [`load`](Self::load) instead.
+    /// Refer to [`Wallet::create`] for more.
     pub fn create_with_params(params: CreateParams) -> Result<Self, DescriptorError> {
-        let secp = params.secp;
+        let secp = SecpCtx::new();
         let network = params.network;
         let genesis_hash = params
             .genesis_hash
             .unwrap_or(genesis_block(network).block_hash());
-
         let (chain, chain_changeset) = LocalChain::from_genesis_hash(genesis_hash);
 
-        check_wallet_descriptor(&params.descriptor)?;
-        check_wallet_descriptor(&params.change_descriptor)?;
+        let (descriptor, mut descriptor_keymap) = (params.descriptor)(&secp, network)?;
+        descriptor_keymap.extend(params.descriptor_keymap);
+
+        let (change_descriptor, mut change_descriptor_keymap) =
+            (params.change_descriptor)(&secp, network)?;
+        change_descriptor_keymap.extend(params.change_descriptor_keymap);
+
         let signers = Arc::new(SignersContainer::build(
-            params.descriptor_keymap,
-            &params.descriptor,
+            descriptor_keymap,
+            &descriptor,
             &secp,
         ));
         let change_signers = Arc::new(SignersContainer::build(
-            params.change_descriptor_keymap,
-            &params.change_descriptor,
+            change_descriptor_keymap,
+            &change_descriptor,
             &secp,
         ));
-        let index = create_indexer(
-            params.descriptor,
-            params.change_descriptor,
-            params.lookahead,
-        )?;
+        let index = create_indexer(descriptor, change_descriptor, params.lookahead)?;
 
         let descriptor = index.get_descriptor(&KeychainKind::External).cloned();
         let change_descriptor = index.get_descriptor(&KeychainKind::Internal).cloned();
@@ -370,7 +371,8 @@ impl Wallet {
     ///
     /// Note that the descriptor secret keys are not persisted to the db. You can either add
     /// signers after-the-fact with [`Wallet::add_signer`] or [`Wallet::set_keymap`]. Or you can
-    /// construct wallet using [`Wallet::load_with_descriptors`].
+    /// add keys when building the wallet using [`LoadParams::keymap`] and/or
+    /// [`LoadParams::descriptors`].
     ///
     /// # Synopsis
     ///
@@ -394,14 +396,15 @@ impl Wallet {
     /// # let genesis_hash = BlockHash::all_zeros();
     /// let mut conn = bdk_wallet::rusqlite::Connection::open(file_path)?;
     /// let mut wallet = Wallet::load()
-    ///     // manually include private keys
-    ///     // the alternative is to use `Wallet::load_with_descriptors`
+    ///     // check loaded descriptors matches these values and extract private keys
+    ///     .descriptors(EXTERNAL_DESC, INTERNAL_DESC)
+    ///     // you can also manually add private keys
     ///     .keymap(KeychainKind::External, external_keymap)
     ///     .keymap(KeychainKind::Internal, internal_keymap)
-    ///     // set a lookahead for our indexer
-    ///     .lookahead(101)
     ///     // ensure loaded wallet's genesis hash matches this value
     ///     .genesis_hash(genesis_hash)
+    ///     // set a lookahead for our indexer
+    ///     .lookahead(101)
     ///     .load_wallet(&mut conn)?
     ///     .expect("must have data to load wallet");
     /// # Ok(())
@@ -411,59 +414,9 @@ impl Wallet {
         LoadParams::new()
     }
 
-    /// Build [`Wallet`] by loading from persistence or [`ChangeSet`]. This fails if the loaded
-    /// wallet has a different `network`.
-    ///
-    /// Note that the descriptor secret keys are not persisted to the db. You can either add
-    /// signers after-the-fact with [`Wallet::add_signer`] or [`Wallet::set_keymap`]. Or you can
-    /// construct wallet using [`Wallet::load_with_descriptors`].
-    pub fn load_with_network(network: Network) -> LoadParams {
-        LoadParams::with_network(network)
-    }
-
-    /// Build [`Wallet`] by loading from persistence or [`ChangeSet`]. This fails if the loaded
-    /// wallet has a different `network`, `descriptor` or `change_descriptor`.
-    ///
-    /// If the passed-in descriptors contains secret keys, the keys will be included in the
-    /// constructed wallet (which means you can sign transactions).
-    pub fn load_with_descriptors<E: IntoWalletDescriptor>(
-        descriptor: E,
-        change_descriptor: E,
-        network: Network,
-    ) -> Result<LoadParams, DescriptorError> {
-        LoadParams::with_descriptors(descriptor, change_descriptor, network)
-    }
-
-    /// Load [`Wallet`] from the given previously persisted [`ChangeSet`].
-    ///
-    /// Note that the descriptor secret keys are not persisted to the db; this means that after
-    /// calling this method the [`Wallet`] **won't** know the secret keys, and as such, won't be
-    /// able to sign transactions.
-    ///
-    /// If you wish to use the wallet to sign transactions, you need to add the secret keys
-    /// manually to the [`Wallet`]:
-    ///
-    /// ```rust,no_run
-    /// # use bdk_wallet::Wallet;
-    /// # use bitcoin::Network;
-    /// # use bdk_wallet::{LoadParams, KeychainKind, PersistedWallet};
-    /// use bdk_chain::sqlite::Connection;
-    /// #
-    /// # fn main() -> anyhow::Result<()> {
-    /// # let temp_dir = tempfile::tempdir().expect("must create tempdir");
-    /// # let file_path = temp_dir.path().join("store.db");
-    /// const EXTERNAL_DESC: &str = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/0/*)";
-    /// const INTERNAL_DESC: &str = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/1/*)";
+    /// Load [`Wallet`] from the given previously persisted [`ChangeSet`] and `params`.
     ///
-    /// let mut conn = Connection::open(file_path)?;
-    /// let mut wallet: PersistedWallet =
-    ///     LoadParams::with_descriptors(EXTERNAL_DESC, INTERNAL_DESC, Network::Testnet)?
-    ///     .load_wallet(&mut conn)?
-    ///     .expect("db should have data to load wallet");
-    ///
-    /// # Ok(())
-    /// # }
-    /// ```
+    /// Refer to [`Wallet::load`] for more.
     pub fn load_with_params(
         changeset: ChangeSet,
         params: LoadParams,
@@ -476,13 +429,16 @@ impl Wallet {
         let chain = LocalChain::from_changeset(changeset.local_chain)
             .map_err(|_| LoadError::MissingGenesis)?;
 
+        let mut descriptor_keymap = params.descriptor_keymap;
         let descriptor = changeset
             .descriptor
             .ok_or(LoadError::MissingDescriptor(KeychainKind::External))?;
+        check_wallet_descriptor(&descriptor).map_err(LoadError::Descriptor)?;
+
+        let mut change_descriptor_keymap = params.change_descriptor_keymap;
         let change_descriptor = changeset
             .change_descriptor
             .ok_or(LoadError::MissingDescriptor(KeychainKind::Internal))?;
-        check_wallet_descriptor(&descriptor).map_err(LoadError::Descriptor)?;
         check_wallet_descriptor(&change_descriptor).map_err(LoadError::Descriptor)?;
 
         // checks
@@ -503,6 +459,10 @@ impl Wallet {
             }
         }
         if let Some(exp_descriptor) = params.check_descriptor {
+            let (exp_descriptor, keymap) =
+                (exp_descriptor)(&secp, network).map_err(LoadError::Descriptor)?;
+            descriptor_keymap.extend(keymap);
+
             if descriptor.descriptor_id() != exp_descriptor.descriptor_id() {
                 return Err(LoadError::Mismatch(LoadMismatch::Descriptor {
                     keychain: KeychainKind::External,
@@ -512,6 +472,10 @@ impl Wallet {
             }
         }
         if let Some(exp_change_descriptor) = params.check_change_descriptor {
+            let (exp_change_descriptor, keymap) =
+                (exp_change_descriptor)(&secp, network).map_err(LoadError::Descriptor)?;
+            change_descriptor_keymap.extend(keymap);
+
             if change_descriptor.descriptor_id() != exp_change_descriptor.descriptor_id() {
                 return Err(LoadError::Mismatch(LoadMismatch::Descriptor {
                     keychain: KeychainKind::External,
@@ -522,12 +486,12 @@ impl Wallet {
         }
 
         let signers = Arc::new(SignersContainer::build(
-            params.descriptor_keymap,
+            descriptor_keymap,
             &descriptor,
             &secp,
         ));
         let change_signers = Arc::new(SignersContainer::build(
-            params.change_descriptor_keymap,
+            change_descriptor_keymap,
             &change_descriptor,
             &secp,
         ));
@@ -1092,11 +1056,12 @@ impl Wallet {
     /// ## Example
     ///
     /// ```
-    /// # use bdk_wallet::{CreateParams, KeychainKind};
+    /// # use bdk_wallet::{Wallet, KeychainKind};
     /// # use bdk_wallet::bitcoin::Network;
     /// let descriptor = "wpkh(tprv8ZgxMBicQKsPe73PBRSmNbTfbcsZnwWhz5eVmhHpi31HW29Z7mc9B4cWGRQzopNUzZUT391DeDJxL2PefNunWyLgqCKRMDkU1s2s8bAfoSk/84'/1'/0'/0/*)";
     /// let change_descriptor = "wpkh(tprv8ZgxMBicQKsPe73PBRSmNbTfbcsZnwWhz5eVmhHpi31HW29Z7mc9B4cWGRQzopNUzZUT391DeDJxL2PefNunWyLgqCKRMDkU1s2s8bAfoSk/84'/1'/0'/1/*)";
-    /// let wallet = CreateParams::new(descriptor, change_descriptor, Network::Testnet)?
+    /// let wallet = Wallet::create(descriptor, change_descriptor)
+    ///     .network(Network::Testnet)
     ///     .create_wallet_no_persist()?;
     /// for secret_key in wallet.get_signers(KeychainKind::External).signers().iter().filter_map(|s| s.descriptor_secret_key()) {
     ///     // secret_key: tprv8ZgxMBicQKsPe73PBRSmNbTfbcsZnwWhz5eVmhHpi31HW29Z7mc9B4cWGRQzopNUzZUT391DeDJxL2PefNunWyLgqCKRMDkU1s2s8bAfoSk/84'/0'/0'/0/*
@@ -2452,18 +2417,14 @@ macro_rules! doctest_wallet {
     () => {{
         use $crate::bitcoin::{BlockHash, Transaction, absolute, TxOut, Network, hashes::Hash};
         use $crate::chain::{ConfirmationBlockTime, BlockId, TxGraph};
-        use $crate::{Update, CreateParams, KeychainKind};
+        use $crate::{Update, KeychainKind, Wallet};
         let descriptor = "tr([73c5da0a/86'/0'/0']tprv8fMn4hSKPRC1oaCPqxDb1JWtgkpeiQvZhsr8W2xuy3GEMkzoArcAWTfJxYb6Wj8XNNDWEjfYKK4wGQXh3ZUXhDF2NcnsALpWTeSwarJt7Vc/0/*)";
         let change_descriptor = "tr([73c5da0a/86'/0'/0']tprv8fMn4hSKPRC1oaCPqxDb1JWtgkpeiQvZhsr8W2xuy3GEMkzoArcAWTfJxYb6Wj8XNNDWEjfYKK4wGQXh3ZUXhDF2NcnsALpWTeSwarJt7Vc/1/*)";
 
-        let mut wallet = CreateParams::new(
-            descriptor,
-            change_descriptor,
-            Network::Regtest,
-        )
-        .unwrap()
-        .create_wallet_no_persist()
-        .unwrap();
+        let mut wallet = Wallet::create(descriptor, change_descriptor)
+            .network(Network::Regtest)
+            .create_wallet_no_persist()
+            .unwrap();
         let address = wallet.peek_address(KeychainKind::External, 0).address;
         let tx = Transaction {
             version: transaction::Version::ONE,
index f6fce556f7e0b9289e8466cc97692a1461d3d2d1..563082a1c854cdbb3fdd51317ef2b5b0895d32e0 100644 (file)
@@ -1,53 +1,58 @@
+use alloc::boxed::Box;
 use bdk_chain::{keychain_txout::DEFAULT_LOOKAHEAD, PersistAsyncWith, PersistWith};
 use bitcoin::{BlockHash, Network};
 use miniscript::descriptor::KeyMap;
 
 use crate::{
     descriptor::{DescriptorError, ExtendedDescriptor, IntoWalletDescriptor},
+    utils::SecpCtx,
     KeychainKind, Wallet,
 };
 
-use super::{utils::SecpCtx, ChangeSet, LoadError, PersistedWallet};
+use super::{ChangeSet, LoadError, PersistedWallet};
+
+/// This atrocity is to avoid having type parameters on [`CreateParams`] and [`LoadParams`].
+///
+/// The better option would be to do `Box<dyn IntoWalletDescriptor>`, but we cannot due to Rust's
+/// [object safety rules](https://doc.rust-lang.org/reference/items/traits.html#object-safety).
+type DescriptorToExtract = Box<
+    dyn FnOnce(&SecpCtx, Network) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError>
+        + 'static,
+>;
+
+fn make_descriptor_to_extract<D>(descriptor: D) -> DescriptorToExtract
+where
+    D: IntoWalletDescriptor + 'static,
+{
+    Box::new(|secp, network| descriptor.into_wallet_descriptor(secp, network))
+}
 
 /// Parameters for [`Wallet::create`] or [`PersistedWallet::create`].
-#[derive(Debug, Clone)]
 #[must_use]
 pub struct CreateParams {
-    pub(crate) descriptor: ExtendedDescriptor,
+    pub(crate) descriptor: DescriptorToExtract,
     pub(crate) descriptor_keymap: KeyMap,
-    pub(crate) change_descriptor: ExtendedDescriptor,
+    pub(crate) change_descriptor: DescriptorToExtract,
     pub(crate) change_descriptor_keymap: KeyMap,
     pub(crate) network: Network,
     pub(crate) genesis_hash: Option<BlockHash>,
     pub(crate) lookahead: u32,
-    pub(crate) secp: SecpCtx,
 }
 
 impl CreateParams {
     /// Construct parameters with provided `descriptor`, `change_descriptor` and `network`.
     ///
     /// Default values: `genesis_hash` = `None`, `lookahead` = [`DEFAULT_LOOKAHEAD`]
-    pub fn new<E: IntoWalletDescriptor>(
-        descriptor: E,
-        change_descriptor: E,
-        network: Network,
-    ) -> Result<Self, DescriptorError> {
-        let secp = SecpCtx::default();
-
-        let (descriptor, descriptor_keymap) = descriptor.into_wallet_descriptor(&secp, network)?;
-        let (change_descriptor, change_descriptor_keymap) =
-            change_descriptor.into_wallet_descriptor(&secp, network)?;
-
-        Ok(Self {
-            descriptor,
-            descriptor_keymap,
-            change_descriptor,
-            change_descriptor_keymap,
-            network,
+    pub fn new<D: IntoWalletDescriptor + 'static>(descriptor: D, change_descriptor: D) -> Self {
+        Self {
+            descriptor: make_descriptor_to_extract(descriptor),
+            descriptor_keymap: KeyMap::default(),
+            change_descriptor: make_descriptor_to_extract(change_descriptor),
+            change_descriptor_keymap: KeyMap::default(),
+            network: Network::Bitcoin,
             genesis_hash: None,
             lookahead: DEFAULT_LOOKAHEAD,
-            secp,
-        })
+        }
     }
 
     /// Extend the given `keychain`'s `keymap`.
@@ -60,6 +65,12 @@ impl CreateParams {
         self
     }
 
+    /// Set `network`.
+    pub fn network(mut self, network: Network) -> Self {
+        self.network = network;
+        self
+    }
+
     /// Use a custom `genesis_hash`.
     pub fn genesis_hash(mut self, genesis_hash: BlockHash) -> Self {
         self.genesis_hash = Some(genesis_hash);
@@ -102,16 +113,14 @@ impl CreateParams {
 
 /// Parameters for [`Wallet::load`] or [`PersistedWallet::load`].
 #[must_use]
-#[derive(Debug, Clone)]
 pub struct LoadParams {
     pub(crate) descriptor_keymap: KeyMap,
     pub(crate) change_descriptor_keymap: KeyMap,
     pub(crate) lookahead: u32,
     pub(crate) check_network: Option<Network>,
     pub(crate) check_genesis_hash: Option<BlockHash>,
-    pub(crate) check_descriptor: Option<ExtendedDescriptor>,
-    pub(crate) check_change_descriptor: Option<ExtendedDescriptor>,
-    pub(crate) secp: SecpCtx,
+    pub(crate) check_descriptor: Option<DescriptorToExtract>,
+    pub(crate) check_change_descriptor: Option<DescriptorToExtract>,
 }
 
 impl LoadParams {
@@ -127,39 +136,9 @@ impl LoadParams {
             check_genesis_hash: None,
             check_descriptor: None,
             check_change_descriptor: None,
-            secp: SecpCtx::new(),
-        }
-    }
-
-    /// Construct parameters with `network` check.
-    pub fn with_network(network: Network) -> Self {
-        Self {
-            check_network: Some(network),
-            ..Default::default()
         }
     }
 
-    /// Construct parameters with descriptor checks.
-    pub fn with_descriptors<E: IntoWalletDescriptor>(
-        descriptor: E,
-        change_descriptor: E,
-        network: Network,
-    ) -> Result<Self, DescriptorError> {
-        let mut params = Self::with_network(network);
-        let secp = &params.secp;
-
-        let (descriptor, descriptor_keymap) = descriptor.into_wallet_descriptor(secp, network)?;
-        params.check_descriptor = Some(descriptor);
-        params.descriptor_keymap = descriptor_keymap;
-
-        let (change_descriptor, change_descriptor_keymap) =
-            change_descriptor.into_wallet_descriptor(secp, network)?;
-        params.check_change_descriptor = Some(change_descriptor);
-        params.change_descriptor_keymap = change_descriptor_keymap;
-
-        Ok(params)
-    }
-
     /// Extend the given `keychain`'s `keymap`.
     pub fn keymap(mut self, keychain: KeychainKind, keymap: KeyMap) -> Self {
         match keychain {
@@ -170,6 +149,23 @@ impl LoadParams {
         self
     }
 
+    /// Checks that `descriptor` of `keychain` matches this, and extracts private keys (if
+    /// avaliable).
+    pub fn descriptors<D>(mut self, descriptor: D, change_descriptor: D) -> Self
+    where
+        D: IntoWalletDescriptor + 'static,
+    {
+        self.check_descriptor = Some(make_descriptor_to_extract(descriptor));
+        self.check_change_descriptor = Some(make_descriptor_to_extract(change_descriptor));
+        self
+    }
+
+    /// Check for `network`.
+    pub fn network(mut self, network: Network) -> Self {
+        self.check_network = Some(network);
+        self
+    }
+
     /// Check for a `genesis_hash`.
     pub fn genesis_hash(mut self, genesis_hash: BlockHash) -> Self {
         self.check_genesis_hash = Some(genesis_hash);
index c53eb6cd6b1e864cbe40b4404e4ed0fe2ee9dc0c..946ac20def3158992d5ade0ad3ece6bc863f6602 100644 (file)
@@ -69,7 +69,8 @@
 //!
 //! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/0/*)";
 //! let change_descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/1/*)";
-//! let mut wallet = CreateParams::new(descriptor, change_descriptor, Network::Testnet)?
+//! let mut wallet = Wallet::create(descriptor, change_descriptor)
+//!     .network(Network::Testnet)
 //!     .create_wallet_no_persist()?;
 //! wallet.add_signer(
 //!     KeychainKind::External,
index 0cdbda5a86d201bd5937d30f0906bff6f9d9ed3c..288560b0ac341681be28885a5998ebcdbc82668e 100644 (file)
@@ -13,8 +13,8 @@ use std::str::FromStr;
 /// to a foreign address and one returning 50_000 back to the wallet. The remaining 1000
 /// sats are the transaction fee.
 pub fn get_funded_wallet_with_change(descriptor: &str, change: &str) -> (Wallet, bitcoin::Txid) {
-    let mut wallet = CreateParams::new(descriptor, change, Network::Regtest)
-        .expect("must parse descriptors")
+    let mut wallet = Wallet::create(descriptor.to_string(), change.to_string())
+        .network(Network::Regtest)
         .create_wallet_no_persist()
         .expect("descriptors must be valid");
 
index edd2827b23a58b9b91cfda0b9f102e0109c9e153..94d4b07e1e16645ee4151c67614bcfc048184285 100644 (file)
@@ -122,7 +122,8 @@ fn wallet_is_persisted() -> anyhow::Result<()> {
         // create new wallet
         let wallet_spk_index = {
             let mut db = create_db(&file_path)?;
-            let mut wallet = CreateParams::new(external_desc, internal_desc, Network::Testnet)?
+            let mut wallet = Wallet::create(external_desc, internal_desc)
+                .network(Network::Testnet)
                 .create_wallet(&mut db)?;
             wallet.reveal_next_address(KeychainKind::External);
 
@@ -134,10 +135,11 @@ fn wallet_is_persisted() -> anyhow::Result<()> {
         // recover wallet
         {
             let mut db = open_db(&file_path).context("failed to recover db")?;
-            let wallet =
-                LoadParams::with_descriptors(external_desc, internal_desc, Network::Testnet)?
-                    .load_wallet(&mut db)?
-                    .expect("wallet must exist");
+            let wallet = Wallet::load()
+                .descriptors(external_desc, internal_desc)
+                .network(Network::Testnet)
+                .load_wallet(&mut db)?
+                .expect("wallet must exist");
 
             assert_eq!(wallet.network(), Network::Testnet);
             assert_eq!(
@@ -179,8 +181,8 @@ fn wallet_is_persisted() -> anyhow::Result<()> {
 fn test_error_external_and_internal_are_the_same() {
     // identical descriptors should fail to create wallet
     let desc = get_test_wpkh();
-    let err = CreateParams::new(desc, desc, Network::Testnet)
-        .unwrap()
+    let err = Wallet::create(desc, desc)
+        .network(Network::Testnet)
         .create_wallet_no_persist();
     assert!(
         matches!(&err, Err(DescriptorError::ExternalAndInternalAreTheSame)),
@@ -191,8 +193,8 @@ fn test_error_external_and_internal_are_the_same() {
     // public + private of same descriptor should fail to create wallet
     let desc = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/0/*)";
     let change_desc = "wpkh([3c31d632/84'/1'/0']tpubDCYwFkks2cg78N7eoYbBatsFEGje8vW8arSKW4rLwD1AU1s9KJMDRHE32JkvYERuiFjArrsH7qpWSpJATed5ShZbG9KsskA5Rmi6NSYgYN2/0/*)";
-    let err = CreateParams::new(desc, change_desc, Network::Testnet)
-        .unwrap()
+    let err = Wallet::create(desc, change_desc)
+        .network(Network::Testnet)
         .create_wallet_no_persist();
     assert!(
         matches!(err, Err(DescriptorError::ExternalAndInternalAreTheSame)),
@@ -1154,8 +1156,8 @@ fn test_create_tx_policy_path_required() {
 #[test]
 fn test_create_tx_policy_path_no_csv() {
     let (descriptor, change_descriptor) = get_test_wpkh_with_change_desc();
-    let mut wallet = CreateParams::new(descriptor, change_descriptor, Network::Regtest)
-        .expect("must parse")
+    let mut wallet = Wallet::create(descriptor, change_descriptor)
+        .network(Network::Regtest)
         .create_wallet_no_persist()
         .expect("wallet");
 
@@ -2769,8 +2771,8 @@ fn test_sign_nonstandard_sighash() {
 fn test_unused_address() {
     let descriptor = "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)";
     let change_descriptor = get_test_wpkh();
-    let mut wallet = CreateParams::new(descriptor, change_descriptor, Network::Testnet)
-        .expect("must parse descriptors")
+    let mut wallet = Wallet::create(descriptor, change_descriptor)
+        .network(Network::Testnet)
         .create_wallet_no_persist()
         .expect("wallet");
 
@@ -2800,8 +2802,8 @@ fn test_unused_address() {
 fn test_next_unused_address() {
     let descriptor = "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)";
     let change_descriptor = get_test_wpkh();
-    let mut wallet = CreateParams::new(descriptor, change_descriptor, Network::Testnet)
-        .expect("must parse descriptors")
+    let mut wallet = Wallet::create(descriptor, change_descriptor)
+        .network(Network::Testnet)
         .create_wallet_no_persist()
         .expect("wallet");
     assert_eq!(wallet.derivation_index(KeychainKind::External), None);
@@ -2850,8 +2852,8 @@ fn test_next_unused_address() {
 fn test_peek_address_at_index() {
     let descriptor = "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)";
     let change_descriptor = get_test_wpkh();
-    let mut wallet = CreateParams::new(descriptor, change_descriptor, Network::Testnet)
-        .expect("must parse descriptors")
+    let mut wallet = Wallet::create(descriptor, change_descriptor)
+        .network(Network::Testnet)
         .create_wallet_no_persist()
         .expect("wallet");
 
@@ -2888,11 +2890,11 @@ fn test_peek_address_at_index() {
 
 #[test]
 fn test_peek_address_at_index_not_derivable() {
-    let wallet = CreateParams::new(
-        "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/1)",
-        get_test_wpkh(),
-        Network::Testnet,
-    ).unwrap().create_wallet_no_persist().unwrap();
+    let descriptor = "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/1)";
+    let wallet = Wallet::create(descriptor, get_test_wpkh())
+        .network(Network::Testnet)
+        .create_wallet_no_persist()
+        .unwrap();
 
     assert_eq!(
         wallet.peek_address(KeychainKind::External, 1).to_string(),
@@ -2912,11 +2914,12 @@ fn test_peek_address_at_index_not_derivable() {
 
 #[test]
 fn test_returns_index_and_address() {
-    let mut wallet = CreateParams::new(
-        "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)",
-        get_test_wpkh(),
-        Network::Testnet,
-    ).unwrap().create_wallet_no_persist().unwrap();
+    let descriptor =
+        "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)";
+    let mut wallet = Wallet::create(descriptor, get_test_wpkh())
+        .network(Network::Testnet)
+        .create_wallet_no_persist()
+        .unwrap();
 
     // new index 0
     assert_eq!(
@@ -2982,12 +2985,11 @@ fn test_sending_to_bip350_bech32m_address() {
 fn test_get_address() {
     use bdk_wallet::descriptor::template::Bip84;
     let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
-    let wallet = CreateParams::new(
+    let wallet = Wallet::create(
         Bip84(key, KeychainKind::External),
         Bip84(key, KeychainKind::Internal),
-        Network::Regtest,
     )
-    .unwrap()
+    .network(Network::Regtest)
     .create_wallet_no_persist()
     .unwrap();
 
@@ -3017,8 +3019,8 @@ fn test_get_address() {
 #[test]
 fn test_reveal_addresses() {
     let (desc, change_desc) = get_test_tr_single_sig_xprv_with_change_desc();
-    let mut wallet = CreateParams::new(desc, change_desc, Network::Signet)
-        .expect("must parse")
+    let mut wallet = Wallet::create(desc, change_desc)
+        .network(Network::Signet)
         .create_wallet_no_persist()
         .unwrap();
     let keychain = KeychainKind::External;
@@ -3041,12 +3043,11 @@ fn test_get_address_no_reuse() {
     use std::collections::HashSet;
 
     let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
-    let mut wallet = CreateParams::new(
+    let mut wallet = Wallet::create(
         Bip84(key, KeychainKind::External),
         Bip84(key, KeychainKind::Internal),
-        Network::Regtest,
     )
-    .unwrap()
+    .network(Network::Regtest)
     .create_wallet_no_persist()
     .unwrap();
 
@@ -3517,14 +3518,10 @@ fn test_taproot_sign_derive_index_from_psbt() {
     let mut psbt = builder.finish().unwrap();
 
     // re-create the wallet with an empty db
-    let wallet_empty = CreateParams::new(
-        get_test_tr_single_sig_xprv(),
-        get_test_tr_single_sig(),
-        Network::Regtest,
-    )
-    .unwrap()
-    .create_wallet_no_persist()
-    .unwrap();
+    let wallet_empty = Wallet::create(get_test_tr_single_sig_xprv(), get_test_tr_single_sig())
+        .network(Network::Regtest)
+        .create_wallet_no_persist()
+        .unwrap();
 
     // signing with an empty db means that we will only look at the psbt to infer the
     // derivation index
@@ -3624,8 +3621,8 @@ fn test_taproot_sign_non_default_sighash() {
 #[test]
 fn test_spend_coinbase() {
     let (desc, change_desc) = get_test_wpkh_with_change_desc();
-    let mut wallet = CreateParams::new(desc, change_desc, Network::Regtest)
-        .unwrap()
+    let mut wallet = Wallet::create(desc, change_desc)
+        .network(Network::Regtest)
         .create_wallet_no_persist()
         .unwrap();
 
index 4913db9ac0a19be768fc4d4420fc9a58d8d0aa88..35413a9624034d045f849f588486476a4e285022 100644 (file)
@@ -1,6 +1,5 @@
 use bdk_wallet::file_store::Store;
-use bdk_wallet::CreateParams;
-use bdk_wallet::LoadParams;
+use bdk_wallet::Wallet;
 use std::io::Write;
 use std::str::FromStr;
 
@@ -26,11 +25,15 @@ fn main() -> Result<(), anyhow::Error> {
 
     let mut db = Store::<bdk_wallet::ChangeSet>::open_or_create_new(DB_MAGIC.as_bytes(), db_path)?;
 
-    let load_params = LoadParams::with_descriptors(EXTERNAL_DESC, INTERNAL_DESC, NETWORK)?;
-    let create_params = CreateParams::new(EXTERNAL_DESC, INTERNAL_DESC, NETWORK)?;
-    let mut wallet = match load_params.load_wallet(&mut db)? {
+    let wallet_opt = Wallet::load()
+        .descriptors(EXTERNAL_DESC, INTERNAL_DESC)
+        .network(NETWORK)
+        .load_wallet(&mut db)?;
+    let mut wallet = match wallet_opt {
         Some(wallet) => wallet,
-        None => create_params.create_wallet(&mut db)?,
+        None => Wallet::create(EXTERNAL_DESC, INTERNAL_DESC)
+            .network(NETWORK)
+            .create_wallet(&mut db)?,
     };
 
     let address = wallet.next_unused_address(KeychainKind::External);
index efdf2f669db13a20df8b6ada5ab40b790b48be6c..cccd833952617103da998e5142abd013a1ca9cda 100644 (file)
@@ -5,7 +5,7 @@ use bdk_esplora::{esplora_client, EsploraAsyncExt};
 use bdk_wallet::{
     bitcoin::{Amount, Network},
     rusqlite::Connection,
-    CreateParams, KeychainKind, LoadParams, SignOptions,
+    KeychainKind, SignOptions, Wallet,
 };
 
 const SEND_AMOUNT: Amount = Amount::from_sat(5000);
@@ -22,11 +22,15 @@ const ESPLORA_URL: &str = "http://signet.bitcoindevkit.net";
 async fn main() -> Result<(), anyhow::Error> {
     let mut conn = Connection::open(DB_PATH)?;
 
-    let load_params = LoadParams::with_descriptors(EXTERNAL_DESC, INTERNAL_DESC, NETWORK)?;
-    let create_params = CreateParams::new(EXTERNAL_DESC, INTERNAL_DESC, NETWORK)?;
-    let mut wallet = match load_params.load_wallet(&mut conn)? {
+    let wallet_opt = Wallet::load()
+        .descriptors(EXTERNAL_DESC, INTERNAL_DESC)
+        .network(NETWORK)
+        .load_wallet(&mut conn)?;
+    let mut wallet = match wallet_opt {
         Some(wallet) => wallet,
-        None => create_params.create_wallet(&mut conn)?,
+        None => Wallet::create(EXTERNAL_DESC, INTERNAL_DESC)
+            .network(NETWORK)
+            .create_wallet(&mut conn)?,
     };
 
     let address = wallet.next_unused_address(KeychainKind::External);
index 8075561b9f13c0298d8191626c6f6024c0fbdec1..4c4fe99ed050bf3ba8eaf88f66306f113dd0b559 100644 (file)
@@ -4,7 +4,7 @@ use bdk_esplora::{esplora_client, EsploraExt};
 use bdk_wallet::{
     bitcoin::{Amount, Network},
     file_store::Store,
-    CreateParams, KeychainKind, LoadParams, SignOptions,
+    KeychainKind, SignOptions, Wallet,
 };
 
 const DB_MAGIC: &str = "bdk_wallet_esplora_example";
@@ -21,12 +21,15 @@ const ESPLORA_URL: &str = "http://signet.bitcoindevkit.net";
 fn main() -> Result<(), anyhow::Error> {
     let mut db = Store::<bdk_wallet::ChangeSet>::open_or_create_new(DB_MAGIC.as_bytes(), DB_PATH)?;
 
-    let load_params = LoadParams::with_descriptors(EXTERNAL_DESC, INTERNAL_DESC, NETWORK)?;
-    let create_params = CreateParams::new(EXTERNAL_DESC, INTERNAL_DESC, NETWORK)?;
-
-    let mut wallet = match load_params.load_wallet(&mut db)? {
+    let wallet_opt = Wallet::load()
+        .descriptors(EXTERNAL_DESC, INTERNAL_DESC)
+        .network(NETWORK)
+        .load_wallet(&mut db)?;
+    let mut wallet = match wallet_opt {
         Some(wallet) => wallet,
-        None => create_params.create_wallet(&mut db)?,
+        None => Wallet::create(EXTERNAL_DESC, INTERNAL_DESC)
+            .network(NETWORK)
+            .create_wallet(&mut db)?,
     };
 
     let address = wallet.next_unused_address(KeychainKind::External);
index fea8947af8851d721d724b41eeb64bff640fe62f..2533de644c3eaf87863227f63b828441f43ada6b 100644 (file)
@@ -5,7 +5,7 @@ use bdk_bitcoind_rpc::{
 use bdk_wallet::{
     bitcoin::{Block, Network, Transaction},
     file_store::Store,
-    CreateParams, LoadParams,
+    Wallet,
 };
 use clap::{self, Parser};
 use std::{path::PathBuf, sync::mpsc::sync_channel, thread::spawn, time::Instant};
@@ -88,13 +88,15 @@ fn main() -> anyhow::Result<()> {
     let start_load_wallet = Instant::now();
     let mut db =
         Store::<bdk_wallet::ChangeSet>::open_or_create_new(DB_MAGIC.as_bytes(), args.db_path)?;
-
-    let load_params =
-        LoadParams::with_descriptors(&args.descriptor, &args.change_descriptor, args.network)?;
-    let create_params = CreateParams::new(&args.descriptor, &args.change_descriptor, args.network)?;
-    let mut wallet = match load_params.load_wallet(&mut db)? {
+    let wallet_opt = Wallet::load()
+        .descriptors(args.descriptor.clone(), args.change_descriptor.clone())
+        .network(args.network)
+        .load_wallet(&mut db)?;
+    let mut wallet = match wallet_opt {
         Some(wallet) => wallet,
-        None => create_params.create_wallet(&mut db)?,
+        None => Wallet::create(args.descriptor, args.change_descriptor)
+            .network(args.network)
+            .create_wallet(&mut db)?,
     };
     println!(
         "Loaded wallet in {}s",