+++ /dev/null
-use crate::{ConfirmationBlockTime, Merge};
-
-type IndexedTxGraphChangeSet =
- crate::indexed_tx_graph::ChangeSet<ConfirmationBlockTime, crate::keychain_txout::ChangeSet>;
-
-/// A changeset containing [`crate`] structures typically persisted together.
-#[derive(Default, Debug, Clone, PartialEq)]
-#[cfg_attr(
- feature = "serde",
- derive(crate::serde::Deserialize, crate::serde::Serialize),
- serde(crate = "crate::serde")
-)]
-pub struct WalletChangeSet {
- /// Descriptor for recipient addresses.
- pub descriptor: Option<miniscript::Descriptor<miniscript::DescriptorPublicKey>>,
- /// Descriptor for change addresses.
- pub change_descriptor: Option<miniscript::Descriptor<miniscript::DescriptorPublicKey>>,
- /// Stores the network type of the transaction data.
- pub network: Option<bitcoin::Network>,
- /// Changes to the [`LocalChain`](crate::local_chain::LocalChain).
- pub local_chain: crate::local_chain::ChangeSet,
- /// Changes to [`TxGraph`](crate::tx_graph::TxGraph).
- pub tx_graph: crate::tx_graph::ChangeSet<crate::ConfirmationBlockTime>,
- /// Changes to [`KeychainTxOutIndex`](crate::keychain_txout::KeychainTxOutIndex).
- pub indexer: crate::keychain_txout::ChangeSet,
-}
-
-impl Merge for WalletChangeSet {
- /// Merge another [`WalletChangeSet`] into itself.
- ///
- /// The `keychains_added` field respects the invariants of... TODO: FINISH THIS!
- fn merge(&mut self, other: Self) {
- if other.descriptor.is_some() {
- debug_assert!(
- self.descriptor.is_none() || self.descriptor == other.descriptor,
- "descriptor must never change"
- );
- self.descriptor = other.descriptor;
- }
- if other.change_descriptor.is_some() {
- debug_assert!(
- self.change_descriptor.is_none()
- || self.change_descriptor == other.change_descriptor,
- "change descriptor must never change"
- );
- }
- if other.network.is_some() {
- debug_assert!(
- self.network.is_none() || self.network == other.network,
- "network must never change"
- );
- self.network = other.network;
- }
-
- crate::Merge::merge(&mut self.local_chain, other.local_chain);
- crate::Merge::merge(&mut self.tx_graph, other.tx_graph);
- crate::Merge::merge(&mut self.indexer, other.indexer);
- }
-
- fn is_empty(&self) -> bool {
- self.descriptor.is_none()
- && self.change_descriptor.is_none()
- && self.network.is_none()
- && self.local_chain.is_empty()
- && self.tx_graph.is_empty()
- && self.indexer.is_empty()
- }
-}
-
-#[cfg(feature = "sqlite")]
-impl WalletChangeSet {
- /// Schema name for wallet.
- pub const WALLET_SCHEMA_NAME: &'static str = "bdk_wallet";
- /// Name of table to store wallet descriptors and network.
- pub const WALLET_TABLE_NAME: &'static str = "bdk_wallet";
-
- /// Initialize sqlite tables for wallet schema & table.
- fn init_wallet_sqlite_tables(db_tx: &rusqlite::Transaction) -> rusqlite::Result<()> {
- let schema_v0: &[&str] = &[&format!(
- "CREATE TABLE {} ( \
- id INTEGER PRIMARY KEY NOT NULL CHECK (id = 0), \
- descriptor TEXT, \
- change_descriptor TEXT, \
- network TEXT \
- ) STRICT;",
- Self::WALLET_TABLE_NAME,
- )];
- crate::sqlite::migrate_schema(db_tx, Self::WALLET_SCHEMA_NAME, &[schema_v0])
- }
-
- /// Recover a [`WalletChangeSet`] from sqlite database.
- pub fn from_sqlite(db_tx: &rusqlite::Transaction) -> rusqlite::Result<Self> {
- Self::init_wallet_sqlite_tables(db_tx)?;
- use crate::sqlite::Sql;
- use miniscript::{Descriptor, DescriptorPublicKey};
- use rusqlite::OptionalExtension;
-
- let mut changeset = Self::default();
-
- let mut wallet_statement = db_tx.prepare(&format!(
- "SELECT descriptor, change_descriptor, network FROM {}",
- Self::WALLET_TABLE_NAME,
- ))?;
- let row = wallet_statement
- .query_row([], |row| {
- Ok((
- row.get::<_, Sql<Descriptor<DescriptorPublicKey>>>("descriptor")?,
- row.get::<_, Sql<Descriptor<DescriptorPublicKey>>>("change_descriptor")?,
- row.get::<_, Sql<bitcoin::Network>>("network")?,
- ))
- })
- .optional()?;
- if let Some((Sql(desc), Sql(change_desc), Sql(network))) = row {
- changeset.descriptor = Some(desc);
- changeset.change_descriptor = Some(change_desc);
- changeset.network = Some(network);
- }
-
- changeset.local_chain = crate::local_chain::ChangeSet::from_sqlite(db_tx)?;
- changeset.tx_graph = crate::tx_graph::ChangeSet::<_>::from_sqlite(db_tx)?;
- changeset.indexer = crate::indexer::keychain_txout::ChangeSet::from_sqlite(db_tx)?;
-
- Ok(changeset)
- }
-
- /// Persist [`WalletChangeSet`] to sqlite database.
- pub fn persist_to_sqlite(&self, db_tx: &rusqlite::Transaction) -> rusqlite::Result<()> {
- Self::init_wallet_sqlite_tables(db_tx)?;
- use crate::sqlite::Sql;
- use rusqlite::named_params;
-
- let mut descriptor_statement = db_tx.prepare_cached(&format!(
- "INSERT INTO {}(id, descriptor) VALUES(:id, :descriptor) ON CONFLICT(id) DO UPDATE SET descriptor=:descriptor",
- Self::WALLET_TABLE_NAME,
- ))?;
- if let Some(descriptor) = &self.descriptor {
- descriptor_statement.execute(named_params! {
- ":id": 0,
- ":descriptor": Sql(descriptor.clone()),
- })?;
- }
-
- let mut change_descriptor_statement = db_tx.prepare_cached(&format!(
- "INSERT INTO {}(id, change_descriptor) VALUES(:id, :change_descriptor) ON CONFLICT(id) DO UPDATE SET change_descriptor=:change_descriptor",
- Self::WALLET_TABLE_NAME,
- ))?;
- if let Some(change_descriptor) = &self.change_descriptor {
- change_descriptor_statement.execute(named_params! {
- ":id": 0,
- ":change_descriptor": Sql(change_descriptor.clone()),
- })?;
- }
-
- let mut network_statement = db_tx.prepare_cached(&format!(
- "INSERT INTO {}(id, network) VALUES(:id, :network) ON CONFLICT(id) DO UPDATE SET network=:network",
- Self::WALLET_TABLE_NAME,
- ))?;
- if let Some(network) = self.network {
- network_statement.execute(named_params! {
- ":id": 0,
- ":network": Sql(network),
- })?;
- }
-
- self.local_chain.persist_to_sqlite(db_tx)?;
- self.tx_graph.persist_to_sqlite(db_tx)?;
- self.indexer.persist_to_sqlite(db_tx)?;
- Ok(())
- }
-}
-
-impl From<crate::local_chain::ChangeSet> for WalletChangeSet {
- fn from(chain: crate::local_chain::ChangeSet) -> Self {
- Self {
- local_chain: chain,
- ..Default::default()
- }
- }
-}
-
-impl From<IndexedTxGraphChangeSet> for WalletChangeSet {
- fn from(indexed_tx_graph: IndexedTxGraphChangeSet) -> Self {
- Self {
- tx_graph: indexed_tx_graph.tx_graph,
- indexer: indexed_tx_graph.indexer,
- ..Default::default()
- }
- }
-}
-
-impl From<crate::tx_graph::ChangeSet<ConfirmationBlockTime>> for WalletChangeSet {
- fn from(tx_graph: crate::tx_graph::ChangeSet<ConfirmationBlockTime>) -> Self {
- Self {
- tx_graph,
- ..Default::default()
- }
- }
-}
-
-impl From<crate::keychain_txout::ChangeSet> for WalletChangeSet {
- fn from(indexer: crate::keychain_txout::ChangeSet) -> Self {
- Self {
- indexer,
- ..Default::default()
- }
- }
-}
#[cfg(feature = "miniscript")]
mod spk_iter;
#[cfg(feature = "miniscript")]
-pub use spk_iter::*;
-#[cfg(feature = "miniscript")]
-mod changeset;
-#[cfg(feature = "miniscript")]
-pub use changeset::*;
-#[cfg(feature = "miniscript")]
pub use indexer::keychain_txout;
+#[cfg(feature = "miniscript")]
+pub use spk_iter::*;
#[cfg(feature = "sqlite")]
pub mod sqlite;
#[cfg(feature = "sqlite")]
//! # }
//! ```
//!
-//! [`TransactionSigner`]: bdk_wallet::wallet::signer::TransactionSigner
+//! [`TransactionSigner`]: bdk_wallet::signer::TransactionSigner
mod signer;
pub use signer::*;
// Arc::new(custom_signer),
// );
//
-// let addr = wallet.get_address(bdk_wallet::wallet::AddressIndex::LastUnused);
+// let addr = wallet.get_address(bdk_wallet::AddressIndex::LastUnused);
// let mut builder = wallet.build_tx();
// builder.drain_to(addr.script_pubkey()).drain_wallet();
// let (mut psbt, _) = builder.finish().unwrap();
bip39 = { version = "2.0", optional = true }
[features]
-default = ["std", "file_store"]
+default = ["std"]
std = ["bitcoin/std", "bitcoin/rand-std", "miniscript/std", "bdk_chain/std"]
compiler = ["miniscript/compiler"]
all-keys = ["keys-bip39"]
## Persistence
-To persist `Wallet` state data use a data store crate that reads and writes [`bdk_chain::WalletChangeSet`].
+To persist `Wallet` state data use a data store crate that reads and writes [`ChangeSet`].
**Implementations**
<!-- ```rust -->
<!-- use bdk_wallet::Wallet; -->
-<!-- use bdk_wallet::wallet::AddressIndex::New; -->
+<!-- use bdk_wallet::AddressIndex::New; -->
<!-- use bdk_wallet::bitcoin::Network; -->
<!-- fn main() -> Result<(), bdk_wallet::Error> { -->
<!-- use bdk_wallet::blockchain::ElectrumBlockchain; -->
<!-- use bdk_wallet::electrum_client::Client; -->
-<!-- use bdk_wallet::wallet::AddressIndex::New; -->
+<!-- use bdk_wallet::AddressIndex::New; -->
<!-- use bitcoin::base64; -->
<!-- use bdk_wallet::bitcoin::consensus::serialize; -->
use bdk_wallet::bitcoin::Network;
use bdk_wallet::descriptor::{policy::BuildSatisfaction, ExtractPolicy, IntoWalletDescriptor};
-use bdk_wallet::wallet::signer::SignersContainer;
+use bdk_wallet::signer::SignersContainer;
/// This example describes the use of the BDK's [`bdk_wallet::descriptor::policy`] module.
///
// While the `keymap` can be used to create a `SignerContainer`.
//
// The `SignerContainer` can sign for `PSBT`s.
- // a bdk_wallet::wallet internally uses these to handle transaction signing.
+ // a `bdk_wallet::Wallet` internally uses these to handle transaction signing.
// But they can be used as independent tools also.
let (wallet_desc, keymap) = desc.into_wallet_descriptor(&secp, Network::Testnet)?;
//! ```
//! # use std::sync::Arc;
//! # use bdk_wallet::descriptor::*;
-//! # use bdk_wallet::wallet::signer::*;
+//! # use bdk_wallet::signer::*;
//! # use bdk_wallet::bitcoin::secp256k1::Secp256k1;
//! use bdk_wallet::descriptor::policy::BuildSatisfaction;
//! let secp = Secp256k1::new();
#[doc(hidden)]
#[macro_use]
pub extern crate alloc;
-
+pub extern crate bdk_chain as chain;
+#[cfg(feature = "file_store")]
+pub extern crate bdk_file_store as file_store;
+#[cfg(feature = "keys-bip39")]
+pub extern crate bip39;
pub extern crate bitcoin;
pub extern crate miniscript;
-extern crate serde;
-extern crate serde_json;
-
-#[cfg(feature = "keys-bip39")]
-extern crate bip39;
+pub extern crate serde;
+pub extern crate serde_json;
pub mod descriptor;
pub mod keys;
pub mod psbt;
-pub(crate) mod types;
-pub mod wallet;
+mod types;
+mod wallet;
+pub(crate) use bdk_chain::collections;
+#[cfg(feature = "sqlite")]
+pub use bdk_chain::rusqlite;
+#[cfg(feature = "sqlite")]
+pub use bdk_chain::sqlite;
pub use descriptor::template;
pub use descriptor::HdKeyPaths;
+pub use signer;
+pub use signer::SignOptions;
+pub use tx_builder::*;
pub use types::*;
-pub use wallet::signer;
-pub use wallet::signer::SignOptions;
-pub use wallet::tx_builder::TxBuilder;
-pub use wallet::ChangeSet;
-pub use wallet::CreateParams;
-pub use wallet::LoadParams;
-pub use wallet::PersistedWallet;
-pub use wallet::Wallet;
+pub use wallet::*;
/// Get the version of [`bdk_wallet`](crate) at runtime.
pub fn version() -> &'static str {
env!("CARGO_PKG_VERSION", "unknown")
}
-
-pub use bdk_chain as chain;
-pub(crate) use bdk_chain::collections;
-#[cfg(feature = "sqlite")]
-pub use bdk_chain::rusqlite;
-#[cfg(feature = "sqlite")]
-pub use bdk_chain::sqlite;
-
-pub use chain::WalletChangeSet;
--- /dev/null
+use bdk_chain::{
+ indexed_tx_graph, keychain_txout, local_chain, tx_graph, ConfirmationBlockTime, Merge,
+};
+use miniscript::{Descriptor, DescriptorPublicKey};
+
+type IndexedTxGraphChangeSet =
+ indexed_tx_graph::ChangeSet<ConfirmationBlockTime, keychain_txout::ChangeSet>;
+
+/// A changeset for [`Wallet`](crate::Wallet).
+#[derive(Default, Debug, Clone, PartialEq, serde::Deserialize, serde::Serialize)]
+pub struct ChangeSet {
+ /// Descriptor for recipient addresses.
+ pub descriptor: Option<Descriptor<DescriptorPublicKey>>,
+ /// Descriptor for change addresses.
+ pub change_descriptor: Option<Descriptor<DescriptorPublicKey>>,
+ /// Stores the network type of the transaction data.
+ pub network: Option<bitcoin::Network>,
+ /// Changes to the [`LocalChain`](local_chain::LocalChain).
+ pub local_chain: local_chain::ChangeSet,
+ /// Changes to [`TxGraph`](tx_graph::TxGraph).
+ pub tx_graph: tx_graph::ChangeSet<ConfirmationBlockTime>,
+ /// Changes to [`KeychainTxOutIndex`](keychain_txout::KeychainTxOutIndex).
+ pub indexer: keychain_txout::ChangeSet,
+}
+
+impl Merge for ChangeSet {
+ /// Merge another [`ChangeSet`] into itself.
+ fn merge(&mut self, other: Self) {
+ if other.descriptor.is_some() {
+ debug_assert!(
+ self.descriptor.is_none() || self.descriptor == other.descriptor,
+ "descriptor must never change"
+ );
+ self.descriptor = other.descriptor;
+ }
+ if other.change_descriptor.is_some() {
+ debug_assert!(
+ self.change_descriptor.is_none()
+ || self.change_descriptor == other.change_descriptor,
+ "change descriptor must never change"
+ );
+ }
+ if other.network.is_some() {
+ debug_assert!(
+ self.network.is_none() || self.network == other.network,
+ "network must never change"
+ );
+ self.network = other.network;
+ }
+
+ Merge::merge(&mut self.local_chain, other.local_chain);
+ Merge::merge(&mut self.tx_graph, other.tx_graph);
+ Merge::merge(&mut self.indexer, other.indexer);
+ }
+
+ fn is_empty(&self) -> bool {
+ self.descriptor.is_none()
+ && self.change_descriptor.is_none()
+ && self.network.is_none()
+ && self.local_chain.is_empty()
+ && self.tx_graph.is_empty()
+ && self.indexer.is_empty()
+ }
+}
+
+#[cfg(feature = "sqlite")]
+impl ChangeSet {
+ /// Schema name for wallet.
+ pub const WALLET_SCHEMA_NAME: &'static str = "bdk_wallet";
+ /// Name of table to store wallet descriptors and network.
+ pub const WALLET_TABLE_NAME: &'static str = "bdk_wallet";
+
+ /// Initialize sqlite tables for wallet schema & table.
+ fn init_wallet_sqlite_tables(
+ db_tx: &chain::rusqlite::Transaction,
+ ) -> chain::rusqlite::Result<()> {
+ let schema_v0: &[&str] = &[&format!(
+ "CREATE TABLE {} ( \
+ id INTEGER PRIMARY KEY NOT NULL CHECK (id = 0), \
+ descriptor TEXT, \
+ change_descriptor TEXT, \
+ network TEXT \
+ ) STRICT;",
+ Self::WALLET_TABLE_NAME,
+ )];
+ crate::sqlite::migrate_schema(db_tx, Self::WALLET_SCHEMA_NAME, &[schema_v0])
+ }
+
+ /// Recover a [`ChangeSet`] from sqlite database.
+ pub fn from_sqlite(db_tx: &chain::rusqlite::Transaction) -> chain::rusqlite::Result<Self> {
+ Self::init_wallet_sqlite_tables(db_tx)?;
+ use crate::sqlite::Sql;
+ use chain::rusqlite::OptionalExtension;
+ use miniscript::{Descriptor, DescriptorPublicKey};
+
+ let mut changeset = Self::default();
+
+ let mut wallet_statement = db_tx.prepare(&format!(
+ "SELECT descriptor, change_descriptor, network FROM {}",
+ Self::WALLET_TABLE_NAME,
+ ))?;
+ let row = wallet_statement
+ .query_row([], |row| {
+ Ok((
+ row.get::<_, Sql<Descriptor<DescriptorPublicKey>>>("descriptor")?,
+ row.get::<_, Sql<Descriptor<DescriptorPublicKey>>>("change_descriptor")?,
+ row.get::<_, Sql<bitcoin::Network>>("network")?,
+ ))
+ })
+ .optional()?;
+ if let Some((Sql(desc), Sql(change_desc), Sql(network))) = row {
+ changeset.descriptor = Some(desc);
+ changeset.change_descriptor = Some(change_desc);
+ changeset.network = Some(network);
+ }
+
+ changeset.local_chain = local_chain::ChangeSet::from_sqlite(db_tx)?;
+ changeset.tx_graph = tx_graph::ChangeSet::<_>::from_sqlite(db_tx)?;
+ changeset.indexer = keychain_txout::ChangeSet::from_sqlite(db_tx)?;
+
+ Ok(changeset)
+ }
+
+ /// Persist [`ChangeSet`] to sqlite database.
+ pub fn persist_to_sqlite(
+ &self,
+ db_tx: &chain::rusqlite::Transaction,
+ ) -> chain::rusqlite::Result<()> {
+ Self::init_wallet_sqlite_tables(db_tx)?;
+ use chain::rusqlite::named_params;
+ use chain::sqlite::Sql;
+
+ let mut descriptor_statement = db_tx.prepare_cached(&format!(
+ "INSERT INTO {}(id, descriptor) VALUES(:id, :descriptor) ON CONFLICT(id) DO UPDATE SET descriptor=:descriptor",
+ Self::WALLET_TABLE_NAME,
+ ))?;
+ if let Some(descriptor) = &self.descriptor {
+ descriptor_statement.execute(named_params! {
+ ":id": 0,
+ ":descriptor": Sql(descriptor.clone()),
+ })?;
+ }
+
+ let mut change_descriptor_statement = db_tx.prepare_cached(&format!(
+ "INSERT INTO {}(id, change_descriptor) VALUES(:id, :change_descriptor) ON CONFLICT(id) DO UPDATE SET change_descriptor=:change_descriptor",
+ Self::WALLET_TABLE_NAME,
+ ))?;
+ if let Some(change_descriptor) = &self.change_descriptor {
+ change_descriptor_statement.execute(named_params! {
+ ":id": 0,
+ ":change_descriptor": Sql(change_descriptor.clone()),
+ })?;
+ }
+
+ let mut network_statement = db_tx.prepare_cached(&format!(
+ "INSERT INTO {}(id, network) VALUES(:id, :network) ON CONFLICT(id) DO UPDATE SET network=:network",
+ Self::WALLET_TABLE_NAME,
+ ))?;
+ if let Some(network) = self.network {
+ network_statement.execute(named_params! {
+ ":id": 0,
+ ":network": Sql(network),
+ })?;
+ }
+
+ self.local_chain.persist_to_sqlite(db_tx)?;
+ self.tx_graph.persist_to_sqlite(db_tx)?;
+ self.indexer.persist_to_sqlite(db_tx)?;
+ Ok(())
+ }
+}
+
+impl From<local_chain::ChangeSet> for ChangeSet {
+ fn from(chain: local_chain::ChangeSet) -> Self {
+ Self {
+ local_chain: chain,
+ ..Default::default()
+ }
+ }
+}
+
+impl From<IndexedTxGraphChangeSet> for ChangeSet {
+ fn from(indexed_tx_graph: IndexedTxGraphChangeSet) -> Self {
+ Self {
+ tx_graph: indexed_tx_graph.tx_graph,
+ indexer: indexed_tx_graph.indexer,
+ ..Default::default()
+ }
+ }
+}
+
+impl From<tx_graph::ChangeSet<ConfirmationBlockTime>> for ChangeSet {
+ fn from(tx_graph: tx_graph::ChangeSet<ConfirmationBlockTime>) -> Self {
+ Self {
+ tx_graph,
+ ..Default::default()
+ }
+ }
+}
+
+impl From<keychain_txout::ChangeSet> for ChangeSet {
+ fn from(indexer: keychain_txout::ChangeSet) -> Self {
+ Self {
+ indexer,
+ ..Default::default()
+ }
+ }
+}
//! ```
//! # use std::str::FromStr;
//! # use bitcoin::*;
-//! # use bdk_wallet::wallet::{self, ChangeSet, coin_selection::*, coin_selection};
-//! # use bdk_wallet::wallet::error::CreateTxError;
+//! # use bdk_wallet::{self, ChangeSet, coin_selection::*, coin_selection};
+//! # use bdk_wallet::error::CreateTxError;
//! # use bdk_wallet::*;
-//! # use bdk_wallet::wallet::coin_selection::decide_change;
+//! # use bdk_wallet::coin_selection::decide_change;
//! # use anyhow::Error;
//! #[derive(Debug)]
//! struct AlwaysSpendEverything;
//! ```
//! # use std::str::FromStr;
//! # use bitcoin::*;
-//! # use bdk_wallet::wallet::export::*;
+//! # use bdk_wallet::export::*;
//! # use bdk_wallet::*;
//! let import = r#"{
//! "descriptor": "wpkh([c258d2e4\/84h\/1h\/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe\/0\/*)",
//! ### Export a `Wallet`
//! ```
//! # use bitcoin::*;
-//! # use bdk_wallet::wallet::export::*;
+//! # use bdk_wallet::export::*;
//! # use bdk_wallet::*;
//! let wallet = CreateParams::new(
//! "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
//! ```no_run
//! # use bdk_wallet::bitcoin::Network;
//! # use bdk_wallet::signer::SignerOrdering;
-//! # use bdk_wallet::wallet::hardwaresigner::HWISigner;
-//! # use bdk_wallet::wallet::AddressIndex::New;
+//! # use bdk_wallet::hardwaresigner::HWISigner;
+//! # use bdk_wallet::AddressIndex::New;
//! # use bdk_wallet::{CreateParams, KeychainKind, SignOptions};
//! # use hwi::HWIClient;
//! # use std::sync::Arc;
use bdk_chain::tx_graph::CalculateFeeError;
+mod changeset;
pub mod coin_selection;
pub mod export;
mod params;
pub mod signer;
pub mod tx_builder;
+pub use changeset::*;
pub use params::*;
mod persisted;
pub use persisted::*;
}
}
-/// The changes made to a wallet by applying an [`Update`].
-pub type ChangeSet = bdk_chain::WalletChangeSet;
-
/// A derived address and the index it was found at.
/// For convenience this automatically derefs to `Address`
#[derive(Debug, PartialEq, Eq)]
/// # use std::str::FromStr;
/// # use bitcoin::*;
/// # use bdk_wallet::*;
- /// # use bdk_wallet::wallet::ChangeSet;
- /// # use bdk_wallet::wallet::error::CreateTxError;
+ /// # use bdk_wallet::ChangeSet;
+ /// # use bdk_wallet::error::CreateTxError;
/// # use anyhow::Error;
/// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
/// # let mut wallet = doctest_wallet!();
/// # use std::str::FromStr;
/// # use bitcoin::*;
/// # use bdk_wallet::*;
- /// # use bdk_wallet::wallet::ChangeSet;
- /// # use bdk_wallet::wallet::error::CreateTxError;
+ /// # use bdk_wallet::ChangeSet;
+ /// # use bdk_wallet::error::CreateTxError;
/// # use anyhow::Error;
/// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
/// # let mut wallet = doctest_wallet!();
/// # use std::str::FromStr;
/// # use bitcoin::*;
/// # use bdk_wallet::*;
- /// # use bdk_wallet::wallet::ChangeSet;
- /// # use bdk_wallet::wallet::error::CreateTxError;
+ /// # use bdk_wallet::ChangeSet;
+ /// # use bdk_wallet::error::CreateTxError;
/// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
/// # let mut wallet = doctest_wallet!();
/// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
() => {{
use $crate::bitcoin::{BlockHash, Transaction, absolute, TxOut, Network, hashes::Hash};
use $crate::chain::{ConfirmationBlockTime, BlockId, TxGraph};
- use $crate::wallet::{Update, CreateParams};
- use $crate::KeychainKind;
+ use $crate::{Update, CreateParams, KeychainKind};
let descriptor = "tr([73c5da0a/86'/0'/0']tprv8fMn4hSKPRC1oaCPqxDb1JWtgkpeiQvZhsr8W2xuy3GEMkzoArcAWTfJxYb6Wj8XNNDWEjfYKK4wGQXh3ZUXhDF2NcnsALpWTeSwarJt7Vc/0/*)";
let change_descriptor = "tr([73c5da0a/86'/0'/0']tprv8fMn4hSKPRC1oaCPqxDb1JWtgkpeiQvZhsr8W2xuy3GEMkzoArcAWTfJxYb6Wj8XNNDWEjfYKK4wGQXh3ZUXhDF2NcnsALpWTeSwarJt7Vc/1/*)";
use core::fmt;
-use crate::wallet::{ChangeSet, CreateParams, LoadError, LoadParams};
use crate::{descriptor::DescriptorError, Wallet};
-use bdk_chain::{Merge, PersistWith};
/// Represents a persisted wallet.
pub type PersistedWallet = bdk_chain::Persisted<Wallet>;
#[cfg(feature = "sqlite")]
-impl<'c> PersistWith<bdk_chain::sqlite::Transaction<'c>> for Wallet {
- type CreateParams = CreateParams;
- type LoadParams = LoadParams;
+impl<'c> chain::PersistWith<bdk_chain::sqlite::Transaction<'c>> for Wallet {
+ type CreateParams = crate::CreateParams;
+ type LoadParams = crate::LoadParams;
type CreateError = CreateWithPersistError<bdk_chain::rusqlite::Error>;
type LoadError = LoadWithPersistError<bdk_chain::rusqlite::Error>;
conn: &mut bdk_chain::sqlite::Transaction<'c>,
params: Self::LoadParams,
) -> Result<Option<Self>, Self::LoadError> {
- let changeset = ChangeSet::from_sqlite(conn).map_err(LoadWithPersistError::Persist)?;
- if changeset.is_empty() {
+ let changeset =
+ crate::ChangeSet::from_sqlite(conn).map_err(LoadWithPersistError::Persist)?;
+ if chain::Merge::is_empty(&changeset) {
return Ok(None);
}
Self::load_with_params(changeset, params).map_err(LoadWithPersistError::InvalidChangeSet)
}
#[cfg(feature = "sqlite")]
-impl PersistWith<bdk_chain::sqlite::Connection> for Wallet {
- type CreateParams = CreateParams;
- type LoadParams = LoadParams;
+impl chain::PersistWith<bdk_chain::sqlite::Connection> for Wallet {
+ type CreateParams = crate::CreateParams;
+ type LoadParams = crate::LoadParams;
type CreateError = CreateWithPersistError<bdk_chain::rusqlite::Error>;
type LoadError = LoadWithPersistError<bdk_chain::rusqlite::Error>;
params: Self::CreateParams,
) -> Result<Self, Self::CreateError> {
let mut db_tx = db.transaction().map_err(CreateWithPersistError::Persist)?;
- let wallet = PersistWith::create(&mut db_tx, params)?;
+ let wallet = chain::PersistWith::create(&mut db_tx, params)?;
db_tx.commit().map_err(CreateWithPersistError::Persist)?;
Ok(wallet)
}
params: Self::LoadParams,
) -> Result<Option<Self>, Self::LoadError> {
let mut db_tx = db.transaction().map_err(LoadWithPersistError::Persist)?;
- let wallet_opt = PersistWith::load(&mut db_tx, params)?;
+ let wallet_opt = chain::PersistWith::load(&mut db_tx, params)?;
db_tx.commit().map_err(LoadWithPersistError::Persist)?;
Ok(wallet_opt)
}
db: &mut bdk_chain::sqlite::Connection,
) -> Result<bool, Self::PersistError> {
let mut db_tx = db.transaction()?;
- let has_changes = PersistWith::persist(self, &mut db_tx)?;
+ let has_changes = chain::PersistWith::persist(self, &mut db_tx)?;
db_tx.commit()?;
Ok(has_changes)
}
}
#[cfg(feature = "file_store")]
-impl PersistWith<bdk_file_store::Store<ChangeSet>> for Wallet {
- type CreateParams = CreateParams;
- type LoadParams = LoadParams;
+impl chain::PersistWith<bdk_file_store::Store<crate::ChangeSet>> for Wallet {
+ type CreateParams = crate::CreateParams;
+ type LoadParams = crate::LoadParams;
type CreateError = CreateWithPersistError<std::io::Error>;
- type LoadError = LoadWithPersistError<bdk_file_store::AggregateChangesetsError<ChangeSet>>;
+ type LoadError =
+ LoadWithPersistError<bdk_file_store::AggregateChangesetsError<crate::ChangeSet>>;
type PersistError = std::io::Error;
fn create(
- db: &mut bdk_file_store::Store<ChangeSet>,
+ db: &mut bdk_file_store::Store<crate::ChangeSet>,
params: Self::CreateParams,
) -> Result<Self, Self::CreateError> {
let mut wallet =
}
fn load(
- db: &mut bdk_file_store::Store<ChangeSet>,
+ db: &mut bdk_file_store::Store<crate::ChangeSet>,
params: Self::LoadParams,
) -> Result<Option<Self>, Self::LoadError> {
let changeset = db
fn persist(
&mut self,
- db: &mut bdk_file_store::Store<ChangeSet>,
+ db: &mut bdk_file_store::Store<crate::ChangeSet>,
) -> Result<bool, Self::PersistError> {
if let Some(changeset) = self.take_staged() {
db.append_changeset(&changeset)?;
/// Error from persistence.
Persist(E),
/// Occurs when the loaded changeset cannot construct [`Wallet`].
- InvalidChangeSet(LoadError),
+ InvalidChangeSet(crate::LoadError),
}
impl<E: fmt::Display> fmt::Display for LoadWithPersistError<E> {
//! # use std::str::FromStr;
//! # use bitcoin::*;
//! # use bdk_wallet::*;
-//! # use bdk_wallet::wallet::ChangeSet;
-//! # use bdk_wallet::wallet::error::CreateTxError;
+//! # use bdk_wallet::ChangeSet;
+//! # use bdk_wallet::error::CreateTxError;
//! # use anyhow::Error;
//! # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
//! # let mut wallet = doctest_wallet!();
///
/// ```
/// # use bdk_wallet::*;
-/// # use bdk_wallet::wallet::tx_builder::*;
+/// # use bdk_wallet::tx_builder::*;
/// # use bitcoin::*;
/// # use core::str::FromStr;
-/// # use bdk_wallet::wallet::ChangeSet;
-/// # use bdk_wallet::wallet::error::CreateTxError;
+/// # use bdk_wallet::ChangeSet;
+/// # use bdk_wallet::error::CreateTxError;
/// # use anyhow::Error;
/// # let mut wallet = doctest_wallet!();
/// # let addr1 = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
/// # use std::str::FromStr;
/// # use bitcoin::*;
/// # use bdk_wallet::*;
- /// # use bdk_wallet::wallet::ChangeSet;
- /// # use bdk_wallet::wallet::error::CreateTxError;
+ /// # use bdk_wallet::ChangeSet;
+ /// # use bdk_wallet::error::CreateTxError;
/// # use anyhow::Error;
/// # let to_address =
/// Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
#![allow(unused)]
use bdk_chain::{BlockId, ConfirmationBlockTime, ConfirmationTime, TxGraph};
-use bdk_wallet::{
- wallet::{CreateParams, Update, Wallet},
- KeychainKind, LocalOutput,
-};
+use bdk_wallet::{CreateParams, KeychainKind, LocalOutput, Update, Wallet};
use bitcoin::{
hashes::Hash, transaction, Address, Amount, BlockHash, FeeRate, Network, OutPoint, Transaction,
TxIn, TxOut, Txid,
use assert_matches::assert_matches;
use bdk_chain::{BlockId, ConfirmationTime};
use bdk_chain::{PersistWith, COINBASE_MATURITY};
+use bdk_wallet::coin_selection::{self, LargestFirstCoinSelection};
use bdk_wallet::descriptor::{calc_checksum, DescriptorError, IntoWalletDescriptor};
+use bdk_wallet::error::CreateTxError;
use bdk_wallet::psbt::PsbtUtils;
use bdk_wallet::signer::{SignOptions, SignerError};
-use bdk_wallet::wallet::coin_selection::{self, LargestFirstCoinSelection};
-use bdk_wallet::wallet::error::CreateTxError;
-use bdk_wallet::wallet::tx_builder::AddForeignUtxoError;
-use bdk_wallet::wallet::{AddressInfo, Balance, CreateParams, LoadParams, Wallet};
+use bdk_wallet::tx_builder::AddForeignUtxoError;
use bdk_wallet::KeychainKind;
+use bdk_wallet::{AddressInfo, Balance, CreateParams, LoadParams, Wallet};
use bitcoin::hashes::Hash;
use bitcoin::key::Secp256k1;
use bitcoin::psbt;
}
fn insert_seen_at(wallet: &mut Wallet, txid: Txid, seen_at: u64) {
- use bdk_wallet::wallet::Update;
+ use bdk_wallet::Update;
let mut graph = bdk_chain::TxGraph::default();
let _ = graph.insert_seen_at(txid, seen_at);
wallet
#[test]
fn test_create_tx_add_change() {
- use bdk_wallet::wallet::tx_builder::TxOrdering;
+ use bdk_wallet::tx_builder::TxOrdering;
let seed = [0; 32];
let mut rng: StdRng = SeedableRng::from_seed(seed);
let (mut wallet, _) = get_funded_wallet_wpkh();
project_utxo(tx_a).cmp(&project_utxo(tx_b))
};
- let custom_bip69_ordering = bdk_wallet::wallet::tx_builder::TxOrdering::Custom {
+ let custom_bip69_ordering = bdk_wallet::tx_builder::TxOrdering::Custom {
input_sort: Arc::new(bip69_txin_cmp),
output_sort: Arc::new(bip69_txout_cmp),
};
edition = "2021"
[dependencies]
-bdk_wallet = { path = "../../crates/wallet", feature = ["file_store"] }
+bdk_wallet = { path = "../../crates/wallet", features = ["file_store"] }
bdk_electrum = { path = "../../crates/electrum" }
-bdk_file_store = { path = "../../crates/file_store" }
anyhow = "1"
-use bdk_wallet::wallet::CreateParams;
-use bdk_wallet::wallet::LoadParams;
+use bdk_wallet::file_store::Store;
+use bdk_wallet::CreateParams;
+use bdk_wallet::LoadParams;
use std::io::Write;
use std::str::FromStr;
use bdk_electrum::electrum_client;
use bdk_electrum::BdkElectrumClient;
-use bdk_file_store::Store;
use bdk_wallet::bitcoin::Network;
use bdk_wallet::bitcoin::{Address, Amount};
use bdk_wallet::chain::collections::HashSet;
fn main() -> Result<(), anyhow::Error> {
let db_path = "bdk-electrum-example.db";
- let mut db =
- Store::<bdk_wallet::wallet::ChangeSet>::open_or_create_new(DB_MAGIC.as_bytes(), db_path)?;
+ 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)?;
use bdk_wallet::{
bitcoin::{Amount, Network},
rusqlite::Connection,
- wallet::{CreateParams, LoadParams},
- KeychainKind, SignOptions,
+ CreateParams, KeychainKind, LoadParams, SignOptions,
};
const SEND_AMOUNT: Amount = Amount::from_sat(5000);
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-bdk_wallet = { path = "../../crates/wallet" }
+bdk_wallet = { path = "../../crates/wallet", features = ["file_store"] }
bdk_esplora = { path = "../../crates/esplora", features = ["blocking"] }
-bdk_file_store = { path = "../../crates/file_store" }
anyhow = "1"
use std::{collections::BTreeSet, io::Write};
use bdk_esplora::{esplora_client, EsploraExt};
-use bdk_file_store::Store;
use bdk_wallet::{
bitcoin::{Amount, Network},
- wallet::{CreateParams, LoadParams},
- KeychainKind, SignOptions,
+ file_store::Store,
+ CreateParams, KeychainKind, LoadParams, SignOptions,
};
const DB_MAGIC: &str = "bdk_wallet_esplora_example";
const ESPLORA_URL: &str = "http://signet.bitcoindevkit.net";
fn main() -> Result<(), anyhow::Error> {
- let mut db =
- Store::<bdk_wallet::wallet::ChangeSet>::open_or_create_new(DB_MAGIC.as_bytes(), DB_PATH)?;
+ 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)?;
[dependencies]
bdk_wallet = { path = "../../crates/wallet", features = ["file_store"] }
-bdk_file_store = { path = "../../crates/file_store" }
bdk_bitcoind_rpc = { path = "../../crates/bitcoind_rpc" }
anyhow = "1"
bitcoincore_rpc::{Auth, Client, RpcApi},
Emitter,
};
-use bdk_file_store::Store;
use bdk_wallet::{
bitcoin::{Block, Network, Transaction},
- wallet::{CreateParams, LoadParams},
+ file_store::Store,
+ CreateParams, LoadParams,
};
use clap::{self, Parser};
use std::{path::PathBuf, sync::mpsc::sync_channel, thread::spawn, time::Instant};
);
let start_load_wallet = Instant::now();
- let mut db = Store::<bdk_wallet::wallet::ChangeSet>::open_or_create_new(
- DB_MAGIC.as_bytes(),
- args.db_path,
- )?;
+ 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)?;