Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ To persist `Wallet` state use a data storage crate that reads and writes [`Chang

```rust,no_run
use bdk_wallet::rusqlite;
use bdk_wallet::{KeychainKind, Wallet};
use bdk_wallet::{KeyRing, KeychainKind, Wallet};

// Open or create a new SQLite database for wallet data.
let db_path = "my_wallet.sqlite";
Expand All @@ -92,18 +92,20 @@ let change_descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfS
let mut wallet = match Wallet::load()
.descriptor(KeychainKind::External, Some(descriptor))
.descriptor(KeychainKind::Internal, Some(change_descriptor))
.extract_keys()
.check_network(network)
.load_wallet(&mut conn)?
{
Some(wallet) => wallet,
None => Wallet::create(descriptor, change_descriptor)
.network(network)
.create_wallet(&mut conn)?,
None => {
let mut keyring = KeyRing::new(network);
keyring.add_descriptor(KeychainKind::External, descriptor)?;
keyring.add_descriptor(KeychainKind::Internal, change_descriptor)?;
keyring.into_params()?.create_wallet(&mut conn)?
}
};

// Get a new address to receive bitcoin!
let address_info = wallet.reveal_next_address(KeychainKind::External);
let address_info = wallet.reveal_next_address(KeychainKind::External).expect("keychain must exist");

// Persist new wallet state to database.
wallet.persist(&mut conn)?;
Expand Down
27 changes: 16 additions & 11 deletions examples/bitcoind_rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ use bdk_bitcoind_rpc::{
bitcoincore_rpc::{Auth, Client, RpcApi},
Emitter, MempoolEvent,
};
use bdk_wallet::rusqlite::Connection;
use bdk_wallet::{
bitcoin::{Block, Network},
KeychainKind, Wallet,
};
use bdk_wallet::{rusqlite::Connection, KeyRing};
use clap::{self, Parser};
use std::{
path::PathBuf,
Expand Down Expand Up @@ -97,26 +97,31 @@ fn main() -> anyhow::Result<()> {
let wallet_opt = Wallet::load()
.descriptor(KeychainKind::External, Some(args.descriptor.clone()))
.descriptor(KeychainKind::Internal, args.change_descriptor.clone())
.extract_keys()
.check_network(args.network)
.load_wallet(&mut db)?;
let mut wallet = match wallet_opt {
Some(wallet) => wallet,
None => match &args.change_descriptor {
Some(change_desc) => Wallet::create(args.descriptor.clone(), change_desc.clone())
.network(args.network)
.create_wallet(&mut db)?,
None => Wallet::create_single(args.descriptor.clone())
.network(args.network)
.create_wallet(&mut db)?,
},
None => {
let mut keyring = KeyRing::new(args.network);
keyring.add_descriptor(KeychainKind::External, args.descriptor.clone())?;
match &args.change_descriptor {
Some(change_desc) => {
keyring.add_descriptor(KeychainKind::Internal, change_desc.clone())?;
keyring.into_params()?.create_wallet(&mut db)?
}
None => keyring.into_params()?.create_wallet(&mut db)?,
}
}
};
println!(
"Loaded wallet in {}s",
start_load_wallet.elapsed().as_secs_f32()
);

let address = wallet.reveal_next_address(KeychainKind::External).address;
let address = wallet
.reveal_next_address(KeychainKind::External)
.expect("keychain must exist")
.address;
println!("Wallet address: {address}");

let balance = wallet.balance();
Expand Down
27 changes: 15 additions & 12 deletions examples/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use bitcoin::Network;
use miniscript::policy::Concrete;
use miniscript::Descriptor;

use bdk_wallet::{KeychainKind, Wallet};
use bdk_wallet::{KeyRing, KeychainKind};

/// 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
Expand Down Expand Up @@ -56,23 +56,26 @@ fn main() -> Result<(), Box<dyn Error>> {

println!("Compiled into Descriptor: \n{descriptor}");

let mut keyring = KeyRing::new(Network::Regtest);
keyring.add_descriptor(KeychainKind::External, descriptor)?;

// Create a new wallet from descriptors
let mut wallet = Wallet::create_single(descriptor)
.network(Network::Regtest)
.create_wallet_no_persist()?;
let mut wallet = keyring.into_params()?.create_wallet_no_persist()?;

println!(
"First derived address from the descriptor: \n{}",
wallet.next_unused_address(KeychainKind::External),
wallet
.next_unused_address(KeychainKind::External)
.expect("keychain must exist"),
);

// BDK also has it's own `Policy` structure to represent the spending condition in a more
// human readable json format.
let spending_policy = wallet.policies(KeychainKind::External)?;
println!(
"The BDK spending policy: \n{}",
serde_json::to_string_pretty(&spending_policy)?
);
// // BDK also has it's own `Policy` structure to represent the spending condition in a more
// // human readable json format.
// let spending_policy = wallet.policies(KeychainKind::External)?;
// println!(
// "The BDK spending policy: \n{}",
// serde_json::to_string_pretty(&spending_policy)?
// );

Ok(())
}
45 changes: 38 additions & 7 deletions examples/electrum.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use bdk_electrum::electrum_client;
use bdk_electrum::BdkElectrumClient;
use bdk_wallet::bitcoin::Amount;
use bdk_wallet::bitcoin::FeeRate;

Check warning on line 4 in examples/electrum.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/electrum.rs

Check warning on line 4 in examples/electrum.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/electrum.rs
use bdk_wallet::bitcoin::Network;
use bdk_wallet::chain::collections::HashSet;
use bdk_wallet::psbt::PsbtUtils;
use bdk_wallet::rusqlite::Connection;
use bdk_wallet::KeyRing;
use bdk_wallet::Wallet;

Check warning on line 10 in examples/electrum.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/electrum.rs

Check warning on line 10 in examples/electrum.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/electrum.rs
use bdk_wallet::{KeychainKind, SignOptions};
use bdk_wallet::descriptor::IntoWalletDescriptor;
use std::io::Write;
use std::thread::sleep;
use std::time::Duration;
Expand All @@ -27,17 +29,21 @@
let wallet_opt = Wallet::load()
.descriptor(KeychainKind::External, Some(EXTERNAL_DESC))
.descriptor(KeychainKind::Internal, Some(INTERNAL_DESC))
.extract_keys()
.check_network(NETWORK)
.load_wallet(&mut db)?;
let mut wallet = match wallet_opt {
Some(wallet) => wallet,
None => Wallet::create(EXTERNAL_DESC, INTERNAL_DESC)
.network(NETWORK)
.create_wallet(&mut db)?,
None => {
let mut keyring = KeyRing::new(NETWORK);
keyring.add_descriptor(KeychainKind::External, EXTERNAL_DESC)?;
keyring.add_descriptor(KeychainKind::Internal, INTERNAL_DESC)?;
keyring.into_params()?.create_wallet(&mut db)?
}
};

let address = wallet.next_unused_address(KeychainKind::External);
let address = wallet
.next_unused_address(KeychainKind::External)
.expect("keychain must exist");
wallet.persist(&mut db)?;
println!("Generated Address: {address}");

Expand Down Expand Up @@ -89,7 +95,14 @@
tx_builder.fee_rate(target_fee_rate);

let mut psbt = tx_builder.finish()?;
let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
let finalized = wallet.sign_with_signers(
&mut psbt,
&[
&get_signers(EXTERNAL_DESC, &wallet),
&get_signers(INTERNAL_DESC, &wallet),
],
SignOptions::default(),
)?;
assert!(finalized);
let original_fee = psbt.fee_amount().unwrap();
let tx_feerate = psbt.fee_rate().unwrap();
Expand Down Expand Up @@ -124,7 +137,14 @@
let mut builder = wallet.build_fee_bump(txid).expect("failed to bump tx");
builder.fee_rate(feerate);
let mut bumped_psbt = builder.finish().unwrap();
let finalize_btx = wallet.sign(&mut bumped_psbt, SignOptions::default())?;
let finalize_btx = wallet.sign_with_signers(
&mut bumped_psbt,
&[
&get_signers(EXTERNAL_DESC, &wallet),
&get_signers(INTERNAL_DESC, &wallet),
],
SignOptions::default(),
)?;
assert!(finalize_btx);
let new_fee = bumped_psbt.fee_amount().unwrap();
let bumped_tx = bumped_psbt.extract_tx()?;
Expand Down Expand Up @@ -176,3 +196,14 @@

Ok(())
}

Check warning on line 199 in examples/electrum.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/electrum.rs

Check warning on line 199 in examples/electrum.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/electrum.rs
pub fn get_signers(
desc: impl IntoWalletDescriptor,
wallet: &Wallet<KeychainKind>
) -> bdk_wallet::signer::SignersContainer {
use bdk_wallet::signer::SignersContainer;

let (descriptor, keymap) = desc.into_wallet_descriptor(wallet.secp_ctx(), wallet.network().into())

Check warning on line 206 in examples/electrum.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/electrum.rs

Check warning on line 206 in examples/electrum.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/electrum.rs
.unwrap();
SignersContainer::build(keymap, &descriptor, wallet.secp_ctx())
}
46 changes: 38 additions & 8 deletions examples/esplora_async.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use bdk_esplora::{esplora_client, EsploraAsyncExt};

Check warning on line 1 in examples/esplora_async.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/esplora_async.rs

Check warning on line 1 in examples/esplora_async.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/esplora_async.rs
use bdk_wallet::{
bitcoin::{Amount, FeeRate, Network},
psbt::PsbtUtils,
rusqlite::Connection,
KeychainKind, SignOptions, Wallet,
KeyRing, KeychainKind, SignOptions, Wallet,
descriptor::IntoWalletDescriptor,

Check warning on line 7 in examples/esplora_async.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/esplora_async.rs

Check warning on line 7 in examples/esplora_async.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/esplora_async.rs
};
use std::{collections::BTreeSet, io::Write};
use tokio::time::{sleep, Duration};
Expand All @@ -24,17 +25,21 @@
let wallet_opt = Wallet::load()
.descriptor(KeychainKind::External, Some(EXTERNAL_DESC))
.descriptor(KeychainKind::Internal, Some(INTERNAL_DESC))
.extract_keys()
.check_network(NETWORK)
.load_wallet(&mut db)?;
let mut wallet = match wallet_opt {
Some(wallet) => wallet,
None => Wallet::create(EXTERNAL_DESC, INTERNAL_DESC)
.network(NETWORK)
.create_wallet(&mut db)?,
None => {
let mut keyring = KeyRing::new(NETWORK);
keyring.add_descriptor(KeychainKind::External, EXTERNAL_DESC)?;
keyring.add_descriptor(KeychainKind::Internal, INTERNAL_DESC)?;
keyring.into_params()?.create_wallet(&mut db)?
}
};

let address = wallet.next_unused_address(KeychainKind::External);
let address = wallet
.next_unused_address(KeychainKind::External)
.expect("keychain must exist");
wallet.persist(&mut db)?;
println!("Next unused address: ({}) {address}", address.index);

Expand Down Expand Up @@ -83,7 +88,14 @@
tx_builder.fee_rate(target_fee_rate);

let mut psbt = tx_builder.finish()?;
let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
let finalized = wallet.sign_with_signers(
&mut psbt,
&[
&get_signers(EXTERNAL_DESC, &wallet),
&get_signers(INTERNAL_DESC, &wallet),
],
SignOptions::default(),
)?;
assert!(finalized);
let original_fee = psbt.fee_amount().unwrap();
let tx_feerate = psbt.fee_rate().unwrap();
Expand Down Expand Up @@ -117,7 +129,14 @@
let mut builder = wallet.build_fee_bump(txid).expect("failed to bump tx");
builder.fee_rate(feerate);
let mut bumped_psbt = builder.finish().unwrap();
let finalize_btx = wallet.sign(&mut bumped_psbt, SignOptions::default())?;
let finalize_btx = wallet.sign_with_signers(
&mut bumped_psbt,
&[
&get_signers(EXTERNAL_DESC, &wallet),
&get_signers(INTERNAL_DESC, &wallet),
],
SignOptions::default(),
)?;
assert!(finalize_btx);
let new_fee = bumped_psbt.fee_amount().unwrap();
let bumped_tx = bumped_psbt.extract_tx()?;
Expand Down Expand Up @@ -185,3 +204,14 @@

Ok(())
}

Check warning on line 207 in examples/esplora_async.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/esplora_async.rs

Check warning on line 207 in examples/esplora_async.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/esplora_async.rs
pub fn get_signers(
desc: impl IntoWalletDescriptor,
wallet: &Wallet<KeychainKind>
) -> bdk_wallet::signer::SignersContainer {
use bdk_wallet::signer::SignersContainer;

let (descriptor, keymap) = desc.into_wallet_descriptor(wallet.secp_ctx(), wallet.network().into())

Check warning on line 214 in examples/esplora_async.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/esplora_async.rs

Check warning on line 214 in examples/esplora_async.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/esplora_async.rs
.unwrap();
SignersContainer::build(keymap, &descriptor, wallet.secp_ctx())
}
46 changes: 38 additions & 8 deletions examples/esplora_blocking.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use bdk_esplora::{esplora_client, EsploraExt};
use bdk_wallet::rusqlite::Connection;

Check warning on line 2 in examples/esplora_blocking.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/esplora_blocking.rs

Check warning on line 2 in examples/esplora_blocking.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/esplora_blocking.rs
use bdk_wallet::{
bitcoin::{Amount, FeeRate, Network},
psbt::PsbtUtils,
KeychainKind, SignOptions, Wallet,
KeyRing, KeychainKind, SignOptions, Wallet,
descriptor::IntoWalletDescriptor,
};
use std::thread::sleep;
use std::time::Duration;
Expand All @@ -24,17 +25,21 @@
let wallet_opt = Wallet::load()
.descriptor(KeychainKind::External, Some(EXTERNAL_DESC))
.descriptor(KeychainKind::Internal, Some(INTERNAL_DESC))
.extract_keys()
.check_network(NETWORK)
.load_wallet(&mut db)?;
let mut wallet = match wallet_opt {
Some(wallet) => wallet,
None => Wallet::create(EXTERNAL_DESC, INTERNAL_DESC)
.network(NETWORK)
.create_wallet(&mut db)?,
None => {
let mut keyring = KeyRing::new(NETWORK);
keyring.add_descriptor(KeychainKind::External, EXTERNAL_DESC)?;
keyring.add_descriptor(KeychainKind::Internal, INTERNAL_DESC)?;
keyring.into_params()?.create_wallet(&mut db)?
}
};

let address = wallet.next_unused_address(KeychainKind::External);
let address = wallet
.next_unused_address(KeychainKind::External)
.expect("keychain must exist");
wallet.persist(&mut db)?;
println!(
"Next unused address: ({}) {}",
Expand Down Expand Up @@ -78,7 +83,14 @@
tx_builder.fee_rate(target_fee_rate);

let mut psbt = tx_builder.finish()?;
let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
let finalized = wallet.sign_with_signers(
&mut psbt,
&[
&get_signers(EXTERNAL_DESC, &wallet),
&get_signers(INTERNAL_DESC, &wallet),
],
SignOptions::default(),
)?;
assert!(finalized);
let original_fee = psbt.fee_amount().unwrap();
let tx_feerate = psbt.fee_rate().unwrap();
Expand Down Expand Up @@ -113,7 +125,14 @@
let mut builder = wallet.build_fee_bump(txid).unwrap();
builder.fee_rate(feerate);
let mut new_psbt = builder.finish().unwrap();
let finalize_tx = wallet.sign(&mut new_psbt, SignOptions::default())?;
let finalize_tx = wallet.sign_with_signers(
&mut new_psbt,
&[
&get_signers(EXTERNAL_DESC, &wallet),
&get_signers(INTERNAL_DESC, &wallet),
],
SignOptions::default(),
)?;
assert!(finalize_tx);
let new_fee = new_psbt.fee_amount().unwrap();
let bumped_tx = new_psbt.extract_tx()?;
Expand Down Expand Up @@ -166,3 +185,14 @@

Ok(())
}

Check warning on line 188 in examples/esplora_blocking.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/esplora_blocking.rs

Check warning on line 188 in examples/esplora_blocking.rs

View workflow job for this annotation

GitHub Actions / Rust fmt

Diff in /home/runner/work/bdk_wallet/bdk_wallet/examples/esplora_blocking.rs
pub fn get_signers(
desc: impl IntoWalletDescriptor,
wallet: &Wallet<KeychainKind>
) -> bdk_wallet::signer::SignersContainer {
use bdk_wallet::signer::SignersContainer;

let (descriptor, keymap) = desc.into_wallet_descriptor(wallet.secp_ctx(), wallet.network().into())
.unwrap();
SignersContainer::build(keymap, &descriptor, wallet.secp_ctx())
}
Loading
Loading