Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
resolver = "2"
members = [
"wallet",
"examples/example_wallet_electrum",
"examples/example_wallet_esplora_blocking",
"examples/example_wallet_esplora_async",
"examples/example_wallet_rpc",
"examples/example_wallet_n_keychains"
# "examples/example_wallet_electrum",
# "examples/example_wallet_esplora_blocking",
# "examples/example_wallet_esplora_async",
# "examples/example_wallet_rpc",
]

[workspace.package]
Expand Down
23 changes: 23 additions & 0 deletions wallet/examples/n_keychains.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use bdk_wallet::{KeyRing, Wallet};
use bdk_wallet::bitcoin::Network;
use bdk_wallet::KeychainKind;

const EXTERNAL_DESC: &str = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/0/*)";
const OTHER_DESC_21: &str = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/21/*)";
const OTHER_DESC_33: &str = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/33/*)";
const OTHER_DESC_44: &str = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/44/*)";

fn main() -> Result<(), anyhow::Error> {
let mut keyring = KeyRing::new(EXTERNAL_DESC, Network::Testnet4);
// keyring.add_other_descriptor(OTHER_DESC_21);
// let keychains = keyring.list_keychains();
// println!("{:?}", keychains);

let wallet: Wallet = Wallet::new(keyring).create_wallet_no_persist()?;
let address_1 = wallet.peek_address(KeychainKind::Default, 0).unwrap();
// let address_2 = wallet.peek_address((KeychainKind::Other(), 0).unwrap();

println!("Address {:?} at index {:?} on keychain {:?}", address_1.address, address_1.index, address_1.keychain);

Ok(())
}
36 changes: 21 additions & 15 deletions wallet/src/descriptor/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,17 @@ use super::{ExtendedDescriptor, IntoWalletDescriptor, KeyMap};
use crate::descriptor::DescriptorError;
use crate::keys::{DerivableKey, IntoDescriptorKey, ValidNetworks};
use crate::wallet::utils::SecpCtx;
use crate::{descriptor, KeychainKind};
use crate::descriptor;

/// Type alias for the return type of [`DescriptorTemplate`], [`descriptor!`](crate::descriptor!) and others
pub type DescriptorTemplateOut = (ExtendedDescriptor, KeyMap, ValidNetworks);

#[derive(Clone, Debug)]
pub enum TemplateKeychainKind {
External,
Internal,
}

/// Trait for descriptor templates that can be built into a full descriptor
///
/// Since [`IntoWalletDescriptor`] is implemented for any [`DescriptorTemplate`], they can also be
Expand Down Expand Up @@ -232,7 +238,7 @@ impl<K: IntoDescriptorKey<Tap>> DescriptorTemplate for P2TR<K> {
/// # Ok::<_, Box<dyn std::error::Error>>(())
/// ```
#[derive(Debug, Clone)]
pub struct Bip44<K: DerivableKey<Legacy>>(pub K, pub KeychainKind);
pub struct Bip44<K: DerivableKey<Legacy>>(pub K, pub TemplateKeychainKind);

impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44<K> {
fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
Expand Down Expand Up @@ -271,7 +277,7 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44<K> {
/// # Ok::<_, Box<dyn std::error::Error>>(())
/// ```
#[derive(Debug, Clone)]
pub struct Bip44Public<K: DerivableKey<Legacy>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
pub struct Bip44Public<K: DerivableKey<Legacy>>(pub K, pub bip32::Fingerprint, pub TemplateKeychainKind);

impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44Public<K> {
fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
Expand Down Expand Up @@ -309,7 +315,7 @@ impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44Public<K> {
/// # Ok::<_, Box<dyn std::error::Error>>(())
/// ```
#[derive(Debug, Clone)]
pub struct Bip49<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
pub struct Bip49<K: DerivableKey<Segwitv0>>(pub K, pub TemplateKeychainKind);

impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49<K> {
fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
Expand Down Expand Up @@ -348,7 +354,7 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49<K> {
/// # Ok::<_, Box<dyn std::error::Error>>(())
/// ```
#[derive(Debug, Clone)]
pub struct Bip49Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
pub struct Bip49Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub TemplateKeychainKind);

impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49Public<K> {
fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
Expand Down Expand Up @@ -386,7 +392,7 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49Public<K> {
/// # Ok::<_, Box<dyn std::error::Error>>(())
/// ```
#[derive(Debug, Clone)]
pub struct Bip84<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
pub struct Bip84<K: DerivableKey<Segwitv0>>(pub K, pub TemplateKeychainKind);

impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84<K> {
fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
Expand Down Expand Up @@ -425,7 +431,7 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84<K> {
/// # Ok::<_, Box<dyn std::error::Error>>(())
/// ```
#[derive(Debug, Clone)]
pub struct Bip84Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
pub struct Bip84Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub TemplateKeychainKind);

impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84Public<K> {
fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
Expand Down Expand Up @@ -463,7 +469,7 @@ impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84Public<K> {
/// # Ok::<_, Box<dyn std::error::Error>>(())
/// ```
#[derive(Debug, Clone)]
pub struct Bip86<K: DerivableKey<Tap>>(pub K, pub KeychainKind);
pub struct Bip86<K: DerivableKey<Tap>>(pub K, pub TemplateKeychainKind);

impl<K: DerivableKey<Tap>> DescriptorTemplate for Bip86<K> {
fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
Expand Down Expand Up @@ -502,7 +508,7 @@ impl<K: DerivableKey<Tap>> DescriptorTemplate for Bip86<K> {
/// # Ok::<_, Box<dyn std::error::Error>>(())
/// ```
#[derive(Debug, Clone)]
pub struct Bip86Public<K: DerivableKey<Tap>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
pub struct Bip86Public<K: DerivableKey<Tap>>(pub K, pub bip32::Fingerprint, pub TemplateKeychainKind);

impl<K: DerivableKey<Tap>> DescriptorTemplate for Bip86Public<K> {
fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
Expand All @@ -521,7 +527,7 @@ macro_rules! expand_make_bipxx {
pub(super) fn make_bipxx_private<K: DerivableKey<$ctx>>(
bip: u32,
key: K,
keychain: KeychainKind,
keychain: TemplateKeychainKind,
network: Network,
) -> Result<impl IntoDescriptorKey<$ctx>, DescriptorError> {
let mut derivation_path = alloc::vec::Vec::with_capacity(4);
Expand All @@ -538,10 +544,10 @@ macro_rules! expand_make_bipxx {
derivation_path.push(bip32::ChildNumber::from_hardened_idx(0)?);

match keychain {
KeychainKind::External => {
TemplateKeychainKind::External => {
derivation_path.push(bip32::ChildNumber::from_normal_idx(0)?)
}
KeychainKind::Internal => {
TemplateKeychainKind::Internal => {
derivation_path.push(bip32::ChildNumber::from_normal_idx(1)?)
}
};
Expand All @@ -554,12 +560,12 @@ macro_rules! expand_make_bipxx {
bip: u32,
key: K,
parent_fingerprint: bip32::Fingerprint,
keychain: KeychainKind,
keychain: TemplateKeychainKind,
network: Network,
) -> Result<impl IntoDescriptorKey<$ctx>, DescriptorError> {
let derivation_path: bip32::DerivationPath = match keychain {
KeychainKind::External => vec![bip32::ChildNumber::from_normal_idx(0)?].into(),
KeychainKind::Internal => vec![bip32::ChildNumber::from_normal_idx(1)?].into(),
TemplateKeychainKind::External => vec![bip32::ChildNumber::from_normal_idx(0)?].into(),
TemplateKeychainKind::Internal => vec![bip32::ChildNumber::from_normal_idx(1)?].into(),
};

let source_path = bip32::DerivationPath::from(vec![
Expand Down
Loading