]> Untitled Git - bdk/commitdiff
Use () to indicate a missing blockchain
authorLLFourn <lloyd.fourn@gmail.com>
Wed, 23 Dec 2020 02:48:17 +0000 (13:48 +1100)
committerLLFourn <lloyd.fourn@gmail.com>
Wed, 23 Dec 2020 03:52:29 +0000 (14:52 +1100)
So that:
1. There are no runtime errors
2. There less type annotations needed
3. Less traits and stuff to document

14 files changed:
CHANGELOG.md
README.md
examples/address_validator.rs
examples/compiler.rs
src/blockchain/mod.rs
src/database/any.rs
src/descriptor/template.rs
src/error.rs
src/lib.rs
src/wallet/address_validator.rs
src/wallet/coin_selection.rs
src/wallet/export.rs
src/wallet/mod.rs
src/wallet/signer.rs

index 76fd693500cdc0abf869b9f5864994bdcd09dd2c..19da76e72db4bb1f4a374e2848c91e2e53c728bf 100644 (file)
@@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [Unreleased]
 
+- Remove `BlockchainMarker`, `OfflineClient` and `OfflineWallet` in favor of just using the unit
+  type to mark for a missing client.
+
 ## [v0.2.0] - [0.1.0-beta.1]
 
 ### Project
index 2bf992f201831d0ef607a9d5de9a30a00006b6e9..f13e2d324db405f528c170b1ac5702df0eefbdac 100644 (file)
--- a/README.md
+++ b/README.md
@@ -66,11 +66,10 @@ fn main() -> Result<(), bdk::Error> {
 ### Generate a few addresses
 
 ```rust
-use bdk::{Wallet, OfflineWallet};
-use bdk::database::MemoryDatabase;
+use bdk::{Wallet, database::MemoryDatabase};
 
 fn main() -> Result<(), bdk::Error> {
-    let wallet: OfflineWallet<_> = Wallet::new_offline(
+    let wallet = Wallet::new_offline(
         "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
         Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
         bitcoin::Network::Testnet,
@@ -126,13 +125,12 @@ fn main() -> Result<(), bdk::Error> {
 ### Sign a transaction
 
 ```rust,no_run
-use bdk::{Wallet, OfflineWallet};
-use bdk::database::MemoryDatabase;
+use bdk::{Wallet, database::MemoryDatabase};
 
 use bitcoin::consensus::deserialize;
 
 fn main() -> Result<(), bdk::Error> {
-    let wallet: OfflineWallet<_> = Wallet::new_offline(
+    let wallet = Wallet::new_offline(
         "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
         Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"),
         bitcoin::Network::Testnet,
index eccb1ff46689a93113ed61785b1a5cbf5edbb390..d00a239aeed9bb205f62c1cfc578184f501131ca 100644 (file)
@@ -29,7 +29,7 @@ use bdk::database::MemoryDatabase;
 use bdk::descriptor::HDKeyPaths;
 use bdk::wallet::address_validator::{AddressValidator, AddressValidatorError};
 use bdk::KeychainKind;
-use bdk::{OfflineWallet, Wallet};
+use bdk::Wallet;
 
 use bitcoin::hashes::hex::FromHex;
 use bitcoin::util::bip32::Fingerprint;
@@ -59,7 +59,7 @@ impl AddressValidator for DummyValidator {
 
 fn main() -> Result<(), bdk::Error> {
     let descriptor = "sh(and_v(v:pk(tpubDDpWvmUrPZrhSPmUzCMBHffvC3HyMAPnWDSAQNBTnj1iZeJa7BZQEttFiP4DS4GCcXQHezdXhn86Hj6LHX5EDstXPWrMaSneRWM8yUf6NFd/*),after(630000)))";
-    let mut wallet: OfflineWallet<_> =
+    let mut wallet =
         Wallet::new_offline(descriptor, None, Network::Regtest, MemoryDatabase::new())?;
 
     wallet.add_address_validator(Arc::new(DummyValidator));
index 73f2bd01b6f3c364a914e616ef0c21a52134b8a0..0f1ac4810188c91ce19dca9cb64454edddc98e96 100644 (file)
@@ -40,7 +40,7 @@ use miniscript::policy::Concrete;
 use miniscript::Descriptor;
 
 use bdk::database::memory::MemoryDatabase;
-use bdk::{KeychainKind, OfflineWallet, Wallet};
+use bdk::{KeychainKind, Wallet};
 
 fn main() {
     env_logger::init_from_env(
@@ -98,8 +98,7 @@ fn main() {
         Some("regtest") => Network::Regtest,
         Some("testnet") | _ => Network::Testnet,
     };
-    let wallet: OfflineWallet<_> =
-        Wallet::new_offline(&format!("{}", descriptor), None, network, database).unwrap();
+    let wallet = Wallet::new_offline(&format!("{}", descriptor), None, network, database).unwrap();
 
     info!("... First address: {}", wallet.get_new_address().unwrap());
 
index 9f021275f3ffa5e9e21950905d012bf3f76078bb..665388160a082636f690e2fad60dafc74b8da617 100644 (file)
@@ -79,29 +79,9 @@ pub enum Capability {
     AccurateFees,
 }
 
-/// Marker trait for a blockchain backend
-///
-/// This is a marker trait for blockchain types. It is automatically implemented for types that
-/// implement [`Blockchain`], so as a user of the library you won't have to implement this
-/// manually.
-///
-/// Users of the library will probably never have to implement this trait manually, but they
-/// could still need to import it to define types and structs with generics;
-/// Implementing only the marker trait is pointless, since [`OfflineBlockchain`]
-/// already does that, and whenever [`Blockchain`] is implemented, the marker trait is also
-/// automatically implemented by the library.
-pub trait BlockchainMarker {}
-
-/// The [`BlockchainMarker`] marker trait is automatically implemented for [`Blockchain`] types
-impl<T: Blockchain> BlockchainMarker for T {}
-
-/// Type that only implements [`BlockchainMarker`] and is always "offline"
-pub struct OfflineBlockchain;
-impl BlockchainMarker for OfflineBlockchain {}
-
 /// Trait that defines the actions that must be supported by a blockchain backend
 #[maybe_async]
-pub trait Blockchain: BlockchainMarker {
+pub trait Blockchain {
     /// Return the set of [`Capability`] supported by this backend
     fn get_capabilities(&self) -> HashSet<Capability>;
 
index 0e842b3de3d6392f316c103696c8f84a31391e0a..64dd47722dbaf3461dc196d2620457f41a8c2a34 100644 (file)
 //!
 //! ## Example
 //!
-//! In this example, `wallet_memory` and `wallet_sled` have the same type of `Wallet<OfflineBlockchain, AnyDatabase>`.
+//! In this example, `wallet_memory` and `wallet_sled` have the same type of `Wallet<(), AnyDatabase>`.
 //!
 //! ```no_run
 //! # use bitcoin::Network;
 //! # use bdk::database::{AnyDatabase, MemoryDatabase};
-//! # use bdk::{Wallet, OfflineWallet};
-//! let memory = MemoryDatabase::default().into();
-//! let wallet_memory: OfflineWallet<AnyDatabase> =
+//! # use bdk::{Wallet};
+//! let memory = MemoryDatabase::default();
+//! let wallet_memory =
 //!     Wallet::new_offline("...", None, Network::Testnet, memory)?;
 //!
 //! # #[cfg(feature = "key-value-db")]
 //! # {
-//! let sled = sled::open("my-database")?.open_tree("default_tree")?.into();
-//! let wallet_sled: OfflineWallet<AnyDatabase> =
+//! let sled = sled::open("my-database")?.open_tree("default_tree")?;
+//! let wallet_sled =
 //!     Wallet::new_offline("...", None, Network::Testnet, sled)?;
 //! # }
 //! # Ok::<(), bdk::Error>(())
 //! ```no_run
 //! # use bitcoin::Network;
 //! # use bdk::database::*;
-//! # use bdk::{Wallet, OfflineWallet};
+//! # use bdk::{Wallet};
 //! let config = serde_json::from_str("...")?;
 //! let database = AnyDatabase::from_config(&config)?;
-//! let wallet: OfflineWallet<_> = Wallet::new_offline("...", None, Network::Testnet, database)?;
+//! let wallet = Wallet::new_offline("...", None, Network::Testnet, database)?;
 //! # Ok::<(), bdk::Error>(())
 //! ```
 
index 6b832f301648c31ff9556069fdd35064ff36c498..6a14e919b28adfa31c9b764fe2f3c3872655a019 100644 (file)
@@ -81,13 +81,13 @@ impl<T: DescriptorTemplate> ToWalletDescriptor for T {
 ///
 /// ```
 /// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet, OfflineWallet};
+/// # use bdk::{Wallet};
 /// # use bdk::database::MemoryDatabase;
 /// use bdk::template::P2PKH;
 ///
 /// let key =
 ///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
-/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+/// let wallet = Wallet::new_offline(
 ///     P2PKH(key),
 ///     None,
 ///     Network::Testnet,
@@ -114,13 +114,13 @@ impl<K: ToDescriptorKey<Legacy>> DescriptorTemplate for P2PKH<K> {
 ///
 /// ```
 /// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet, OfflineWallet};
+/// # use bdk::{Wallet};
 /// # use bdk::database::MemoryDatabase;
 /// use bdk::template::P2WPKH_P2SH;
 ///
 /// let key =
 ///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
-/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+/// let wallet = Wallet::new_offline(
 ///     P2WPKH_P2SH(key),
 ///     None,
 ///     Network::Testnet,
@@ -148,13 +148,13 @@ impl<K: ToDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH_P2SH<K> {
 ///
 /// ```
 /// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet, OfflineWallet};
+/// # use bdk::{Wallet};
 /// # use bdk::database::MemoryDatabase;
 /// use bdk::template::P2WPKH;
 ///
 /// let key =
 ///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
-/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+/// let wallet = Wallet::new_offline(
 ///     P2WPKH(key),
 ///     None,
 ///     Network::Testnet,
@@ -186,12 +186,12 @@ impl<K: ToDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH<K> {
 /// ```
 /// # use std::str::FromStr;
 /// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet, OfflineWallet, KeychainKind};
+/// # use bdk::{Wallet,  KeychainKind};
 /// # use bdk::database::MemoryDatabase;
 /// use bdk::template::BIP44;
 ///
 /// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
-/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+/// let wallet = Wallet::new_offline(
 ///     BIP44(key.clone(), KeychainKind::External),
 ///     Some(BIP44(key, KeychainKind::Internal)),
 ///     Network::Testnet,
@@ -224,13 +224,13 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44<K> {
 /// ```
 /// # use std::str::FromStr;
 /// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet, OfflineWallet, KeychainKind};
+/// # use bdk::{Wallet,  KeychainKind};
 /// # use bdk::database::MemoryDatabase;
 /// use bdk::template::BIP44Public;
 ///
 /// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
 /// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
-/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+/// let wallet = Wallet::new_offline(
 ///     BIP44Public(key.clone(), fingerprint, KeychainKind::External),
 ///     Some(BIP44Public(key, fingerprint, KeychainKind::Internal)),
 ///     Network::Testnet,
@@ -260,12 +260,12 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44Public<K> {
 /// ```
 /// # use std::str::FromStr;
 /// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet, OfflineWallet, KeychainKind};
+/// # use bdk::{Wallet,  KeychainKind};
 /// # use bdk::database::MemoryDatabase;
 /// use bdk::template::BIP49;
 ///
 /// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
-/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+/// let wallet = Wallet::new_offline(
 ///     BIP49(key.clone(), KeychainKind::External),
 ///     Some(BIP49(key, KeychainKind::Internal)),
 ///     Network::Testnet,
@@ -298,13 +298,13 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49<K> {
 /// ```
 /// # use std::str::FromStr;
 /// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet, OfflineWallet, KeychainKind};
+/// # use bdk::{Wallet,  KeychainKind};
 /// # use bdk::database::MemoryDatabase;
 /// use bdk::template::BIP49Public;
 ///
 /// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
 /// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
-/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+/// let wallet = Wallet::new_offline(
 ///     BIP49Public(key.clone(), fingerprint, KeychainKind::External),
 ///     Some(BIP49Public(key, fingerprint, KeychainKind::Internal)),
 ///     Network::Testnet,
@@ -334,12 +334,12 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49Public<K> {
 /// ```
 /// # use std::str::FromStr;
 /// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet, OfflineWallet, KeychainKind};
+/// # use bdk::{Wallet,  KeychainKind};
 /// # use bdk::database::MemoryDatabase;
 /// use bdk::template::BIP84;
 ///
 /// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
-/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+/// let wallet = Wallet::new_offline(
 ///     BIP84(key.clone(), KeychainKind::External),
 ///     Some(BIP84(key, KeychainKind::Internal)),
 ///     Network::Testnet,
@@ -372,13 +372,13 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP84<K> {
 /// ```
 /// # use std::str::FromStr;
 /// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet, OfflineWallet, KeychainKind};
+/// # use bdk::{Wallet,  KeychainKind};
 /// # use bdk::database::MemoryDatabase;
 /// use bdk::template::BIP84Public;
 ///
 /// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
 /// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
-/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+/// let wallet = Wallet::new_offline(
 ///     BIP84Public(key.clone(), fingerprint, KeychainKind::External),
 ///     Some(BIP84Public(key, fingerprint, KeychainKind::Internal)),
 ///     Network::Testnet,
index 8f137f1fc32ad86763e4a0edef84d0d77e61c3fc..b1fd9bbf2c89f287971f37954ba0e7112bf14dff 100644 (file)
@@ -89,11 +89,6 @@ pub enum Error {
     /// Signing error
     Signer(crate::wallet::signer::SignerError),
 
-    // Blockchain interface errors
-    /// Thrown when trying to call a method that requires a network connection, [`Wallet::sync`](crate::Wallet::sync) and [`Wallet::broadcast`](crate::Wallet::broadcast)
-    /// This error is thrown when creating the Client for the first time, while recovery attempts are tried
-    /// during the sync
-    OfflineClient,
     /// Progress value must be between `0.0` (included) and `100.0` (included)
     InvalidProgressValue(f32),
     /// Progress update error (maybe the channel has been closed)
index 3991aed641d5fef2acf5a26adff870e39c6b5547..163f4c3dfd4d577944c0edaa42f183f37405eb08 100644 (file)
 //!
 //! ### Example
 //! ```
-//! use bdk::{Wallet, OfflineWallet};
+//! use bdk::{Wallet};
 //! use bdk::database::MemoryDatabase;
 //!
 //! fn main() -> Result<(), bdk::Error> {
-//!     let wallet: OfflineWallet<_> = Wallet::new_offline(
+//!     let wallet = Wallet::new_offline(
 //!         "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
 //!         Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
 //!         bitcoin::Network::Testnet,
 //! ### Example
 //! ```ignore
 //! use base64::decode;
-//! use bdk::{Wallet, OfflineWallet};
+//! use bdk::{Wallet};
 //! use bdk::database::MemoryDatabase;
 //!
 //! use bitcoin::consensus::deserialize;
 //!
 //! fn main() -> Result<(), bdk::Error> {
-//!     let wallet: OfflineWallet<_> = Wallet::new_offline(
+//!     let wallet = Wallet::new_offline(
 //!         "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
 //!         Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"),
 //!         bitcoin::Network::Testnet,
@@ -268,4 +268,4 @@ pub use types::*;
 pub use wallet::address_validator;
 pub use wallet::signer;
 pub use wallet::tx_builder::TxBuilder;
-pub use wallet::{OfflineWallet, Wallet};
+pub use wallet::Wallet;
index 26f15a253cc6d7065ec8b5138b7a4f346fbe4c87..c1555f6cd49d6168e358010cfe59ed6e6db0b1e7 100644 (file)
@@ -66,7 +66,7 @@
 //! }
 //!
 //! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
-//! let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+//! let mut wallet = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
 //! wallet.add_address_validator(Arc::new(PrintAddressAndContinue));
 //!
 //! let address = wallet.get_new_address()?;
index f964f5dcb54f89838d3ae01c840508adc13a3f3c..87808db137d125661fece09ba707f77e99d66426 100644 (file)
@@ -84,7 +84,7 @@
 //!     }
 //! }
 //!
-//! # let wallet: OfflineWallet<_> = Wallet::new_offline("", None, Network::Testnet, bdk::database::MemoryDatabase::default())?;
+//! # let wallet = Wallet::new_offline("", None, Network::Testnet, bdk::database::MemoryDatabase::default())?;
 //! // create wallet, sync, ...
 //!
 //! let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
index 9f17e9d5722bba0cbf178f2a87ba7d2d7c34c7db..cb367b35517e78ae61478b95a6a8b0c56b67dd78 100644 (file)
@@ -43,7 +43,7 @@
 //! }"#;
 //!
 //! let import = WalletExport::from_str(import)?;
-//! let wallet: OfflineWallet<_> = Wallet::new_offline(
+//! let wallet = Wallet::new_offline(
 //!     &import.descriptor(),
 //!     import.change_descriptor().as_ref(),
 //!     Network::Testnet,
@@ -58,7 +58,7 @@
 //! # use bdk::database::*;
 //! # use bdk::wallet::export::*;
 //! # use bdk::*;
-//! let wallet: OfflineWallet<_> = Wallet::new_offline(
+//! let wallet = Wallet::new_offline(
 //!     "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
 //!     Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
 //!     Network::Testnet,
@@ -78,7 +78,6 @@ use serde::{Deserialize, Serialize};
 
 use miniscript::{Descriptor, DescriptorPublicKey, ScriptContext, Terminal};
 
-use crate::blockchain::BlockchainMarker;
 use crate::database::BatchDatabase;
 use crate::wallet::Wallet;
 
@@ -120,7 +119,7 @@ impl WalletExport {
     ///
     /// If the database is empty or `include_blockheight` is false, the `blockheight` field
     /// returned will be `0`.
-    pub fn export_wallet<B: BlockchainMarker, D: BatchDatabase>(
+    pub fn export_wallet<B, D: BatchDatabase>(
         wallet: &Wallet<B, D>,
         label: &str,
         include_blockheight: bool,
@@ -208,7 +207,7 @@ mod test {
     use super::*;
     use crate::database::{memory::MemoryDatabase, BatchOperations};
     use crate::types::TransactionDetails;
-    use crate::wallet::{OfflineWallet, Wallet};
+    use crate::wallet::Wallet;
 
     fn get_test_db() -> MemoryDatabase {
         let mut db = MemoryDatabase::new();
@@ -234,7 +233,7 @@ mod test {
         let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
         let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
 
-        let wallet: OfflineWallet<_> = Wallet::new_offline(
+        let wallet = Wallet::new_offline(
             descriptor,
             Some(change_descriptor),
             Network::Bitcoin,
@@ -258,7 +257,7 @@ mod test {
 
         let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
 
-        let wallet: OfflineWallet<_> =
+        let wallet =
             Wallet::new_offline(descriptor, None, Network::Bitcoin, get_test_db()).unwrap();
         WalletExport::export_wallet(&wallet, "Test Label", true).unwrap();
     }
@@ -272,7 +271,7 @@ mod test {
         let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
         let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/50'/0'/1/*)";
 
-        let wallet: OfflineWallet<_> = Wallet::new_offline(
+        let wallet = Wallet::new_offline(
             descriptor,
             Some(change_descriptor),
             Network::Bitcoin,
@@ -295,7 +294,7 @@ mod test {
                                        [c98b1535/48'/0'/0'/2']tpubDCDi5W4sP6zSnzJeowy8rQDVhBdRARaPhK1axABi8V1661wEPeanpEXj4ZLAUEoikVtoWcyK26TKKJSecSfeKxwHCcRrge9k1ybuiL71z4a/1/*\
                                  ))";
 
-        let wallet: OfflineWallet<_> = Wallet::new_offline(
+        let wallet = Wallet::new_offline(
             descriptor,
             Some(change_descriptor),
             Network::Testnet,
@@ -315,7 +314,7 @@ mod test {
         let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
         let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
 
-        let wallet: OfflineWallet<_> = Wallet::new_offline(
+        let wallet = Wallet::new_offline(
             descriptor,
             Some(change_descriptor),
             Network::Bitcoin,
index 6db8f8d90082acfd1cb1f253e79ec3c0c1a406b1..99e5b05cb33d98f780ee283d850528cc12656acc 100644 (file)
@@ -61,7 +61,7 @@ use signer::{Signer, SignerId, SignerOrdering, SignersContainer};
 use tx_builder::{BumpFee, CreateTx, FeePolicy, TxBuilder, TxBuilderContext};
 use utils::{check_nlocktime, check_nsequence_rbf, descriptor_to_pk_ctx, After, Older, SecpCtx};
 
-use crate::blockchain::{Blockchain, BlockchainMarker, OfflineBlockchain, Progress};
+use crate::blockchain::{Blockchain, Progress};
 use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
 use crate::descriptor::{
     get_checksum, DescriptorMeta, DescriptorScripts, ExtendedDescriptor, ExtractPolicy, Policy,
@@ -73,9 +73,6 @@ use crate::types::*;
 
 const CACHE_ADDR_BATCH_SIZE: u32 = 100;
 
-/// Type alias for a [`Wallet`] that uses [`OfflineBlockchain`]
-pub type OfflineWallet<D> = Wallet<OfflineBlockchain, D>;
-
 /// A Bitcoin wallet
 ///
 /// A wallet takes descriptors, a [`database`](trait@crate::database::Database) and a
@@ -84,7 +81,7 @@ pub type OfflineWallet<D> = Wallet<OfflineBlockchain, D>;
 /// [creating transactions](Wallet::create_tx), etc.
 ///
 /// A wallet can be either "online" if the [`blockchain`](crate::blockchain) type provided
-/// implements [`Blockchain`], or "offline" [`OfflineBlockchain`] is used. Offline wallets only expose
+/// implements [`Blockchain`], or "offline" if it is the unit type `()`. Offline wallets only expose
 /// methods that don't need any interaction with the blockchain to work.
 pub struct Wallet<B, D> {
     descriptor: ExtendedDescriptor,
@@ -99,24 +96,38 @@ pub struct Wallet<B, D> {
 
     current_height: Option<u32>,
 
-    client: Option<B>,
+    client: B,
     database: RefCell<D>,
 
     secp: SecpCtx,
 }
 
-// offline actions, always available
-impl<B, D> Wallet<B, D>
+impl<D> Wallet<(), D>
 where
-    B: BlockchainMarker,
     D: BatchDatabase,
 {
     /// Create a new "offline" wallet
     pub fn new_offline<E: ToWalletDescriptor>(
+        descriptor: E,
+        change_descriptor: Option<E>,
+        network: Network,
+        database: D,
+    ) -> Result<Self, Error> {
+        Self::_new(descriptor, change_descriptor, network, database, (), None)
+    }
+}
+
+impl<B, D> Wallet<B, D>
+where
+    D: BatchDatabase,
+{
+    fn _new<E: ToWalletDescriptor>(
         descriptor: E,
         change_descriptor: Option<E>,
         network: Network,
         mut database: D,
+        client: B,
+        current_height: Option<u32>,
     ) -> Result<Self, Error> {
         let (descriptor, keymap) = descriptor.to_wallet_descriptor(network)?;
         database.check_descriptor_checksum(
@@ -148,18 +159,20 @@ where
             signers,
             change_signers,
             address_validators: Vec::new(),
-
             network,
-
-            current_height: None,
-
-            client: None,
+            current_height,
+            client,
             database: RefCell::new(database),
-
             secp: Secp256k1::new(),
         })
     }
+}
 
+// offline actions, always available
+impl<B, D> Wallet<B, D>
+where
+    D: BatchDatabase,
+{
     /// Return a newly generated address using the external descriptor
     pub fn get_new_address(&self) -> Result<Address, Error> {
         let index = self.fetch_and_increment_index(KeychainKind::External)?;
@@ -241,7 +254,7 @@ where
     /// # use bdk::*;
     /// # use bdk::database::*;
     /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
-    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+    /// # let wallet = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
     /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
     /// let (psbt, details) = wallet.create_tx(
     ///     TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
@@ -556,7 +569,7 @@ where
     /// # use bdk::*;
     /// # use bdk::database::*;
     /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
-    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+    /// # let wallet = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
     /// let txid = Txid::from_str("faff0a466b70f5d5f92bd757a92c1371d4838bdd5bc53a06764e2488e51ce8f8").unwrap();
     /// let (psbt, details) = wallet.bump_fee(
     ///     &txid,
@@ -820,7 +833,7 @@ where
     /// # use bdk::*;
     /// # use bdk::database::*;
     /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
-    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+    /// # let wallet = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
     /// # let (psbt, _) = wallet.create_tx(TxBuilder::new())?;
     /// let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
     /// # Ok::<(), bdk::Error>(())
@@ -1319,12 +1332,15 @@ where
         database: D,
         client: B,
     ) -> Result<Self, Error> {
-        let mut wallet = Self::new_offline(descriptor, change_descriptor, network, database)?;
-
-        wallet.current_height = Some(maybe_await!(client.get_height())? as u32);
-        wallet.client = Some(client);
-
-        Ok(wallet)
+        let current_height = Some(maybe_await!(client.get_height())? as u32);
+        Self::_new(
+            descriptor,
+            change_descriptor,
+            network,
+            database,
+            client,
+            current_height,
+        )
     }
 
     /// Sync the internal database with the blockchain
@@ -1372,13 +1388,13 @@ where
         // TODO: what if i generate an address first and cache some addresses?
         // TODO: we should sync if generating an address triggers a new batch to be stored
         if run_setup {
-            maybe_await!(self.client.as_ref().ok_or(Error::OfflineClient)?.setup(
+            maybe_await!(self.client.setup(
                 None,
                 self.database.borrow_mut().deref_mut(),
                 progress_update,
             ))
         } else {
-            maybe_await!(self.client.as_ref().ok_or(Error::OfflineClient)?.sync(
+            maybe_await!(self.client.sync(
                 None,
                 self.database.borrow_mut().deref_mut(),
                 progress_update,
@@ -1387,8 +1403,8 @@ where
     }
 
     /// Return a reference to the internal blockchain client
-    pub fn client(&self) -> Option<&B> {
-        self.client.as_ref()
+    pub fn client(&self) -> &B {
+        &self.client
     }
 
     /// Get the Bitcoin network the wallet is using.
@@ -1399,11 +1415,7 @@ where
     /// Broadcast a transaction to the network
     #[maybe_async]
     pub fn broadcast(&self, tx: Transaction) -> Result<Txid, Error> {
-        maybe_await!(self
-            .client
-            .as_ref()
-            .ok_or(Error::OfflineClient)?
-            .broadcast(&tx))?;
+        maybe_await!(self.client.broadcast(&tx))?;
 
         Ok(tx.txid())
     }
@@ -1424,7 +1436,7 @@ mod test {
     #[test]
     fn test_cache_addresses_fixed() {
         let db = MemoryDatabase::new();
-        let wallet: OfflineWallet<_> = Wallet::new_offline(
+        let wallet = Wallet::new_offline(
             "wpkh(L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6)",
             None,
             Network::Testnet,
@@ -1458,7 +1470,7 @@ mod test {
     #[test]
     fn test_cache_addresses() {
         let db = MemoryDatabase::new();
-        let wallet: OfflineWallet<_> = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
+        let wallet = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
 
         assert_eq!(
             wallet.get_new_address().unwrap().to_string(),
@@ -1486,7 +1498,7 @@ mod test {
     #[test]
     fn test_cache_addresses_refill() {
         let db = MemoryDatabase::new();
-        let wallet: OfflineWallet<_> = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
+        let wallet = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
 
         assert_eq!(
             wallet.get_new_address().unwrap().to_string(),
@@ -1533,12 +1545,12 @@ mod test {
     pub(crate) fn get_funded_wallet(
         descriptor: &str,
     ) -> (
-        OfflineWallet<MemoryDatabase>,
+        Wallet<(), MemoryDatabase>,
         (String, Option<String>),
         bitcoin::Txid,
     ) {
         let descriptors = testutils!(@descriptors (descriptor));
-        let wallet: OfflineWallet<_> = Wallet::new_offline(
+        let wallet = Wallet::new_offline(
             &descriptors.0,
             None,
             Network::Regtest,
index bdac195b8f70f96a386b2e79d59c6b1317b14242..650bdf2662e2d8547b6a5357ec6a10e9f0c81f0d 100644 (file)
@@ -79,7 +79,7 @@
 //! let custom_signer = CustomSigner::connect();
 //!
 //! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
-//! let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+//! let mut wallet = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
 //! wallet.add_signer(
 //!     KeychainKind::External,
 //!     Fingerprint::from_str("e30f11b8").unwrap().into(),