Skip to content

Commit 4403cdb

Browse files
docs: add complex multi-keychain example
1 parent 29fd25c commit 4403cdb

File tree

1 file changed

+127
-0
lines changed

1 file changed

+127
-0
lines changed

examples/multi_keychain_wallet.rs

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#[allow(dead_code)]
2+
use bdk_wallet::keyring::KeyRing;
3+
use bdk_wallet::Wallet;
4+
use bitcoin::Network;
5+
use miniscript::descriptor::DescriptorType;
6+
7+
// The KeyRing holds a map of keychain identifiers (`K`) to public descriptors. These keychain
8+
// identifiers can be simple (something like the `DescriptorId` or the `KeychainKind` types work
9+
// well, e.g. see the `simple_keyring.rs` example), but they can also be more complex if required by
10+
// the application. This example shows how the keychain identifier can be used to carry metadata
11+
// about the descriptors, which could be used to select which keychain to use in different scenarios
12+
// when calling methods like `Wallet::reveal_next_address`.
13+
14+
// In this example, Johnny has a lot of keychains he keeps track of in his wallet. The map of
15+
// KeychainIdentifier -> Descriptor uses keys that are custom-made at the application layer, and
16+
// useful for its business logic (for example, choose a weekend keychain when Johnny is out partying
17+
// on the weekend).
18+
19+
const DESC_1: &str = "tr([5bc5d243/86'/1'/0']tpubDC72NVP1RK5qwy2QdEfWphDsUBAfBu7oiV6jEFooHP8tGQGFVUeFxhgZxuk1j6EQRJ1YsS3th2RyDgReRqCL4zqp4jtuV2z7gbiqDH2iyUS/0/*)#xh44xwsp";
20+
const DESC_2: &str = "wpkh([5bc5d243/84'/1'/0']tpubDCA4DcMLVSDifbfUxyJaVVAx57ztsVjke6DRYF95jFFgJqvzA9oENovVd7n34NNURmZxFNRB1VLGyDEqxvaZNXie3ZroEGFbeTS2xLYuaN1/0/*)#q8afsa3z";
21+
const DESC_3: &str = "pkh([5bc5d243/44'/1'/0']tpubDDNQtvd8Sg1mXtSGtxRWEcgg7PbPwUSAyAmBonDSL3HLuutthe54Yih4XDYcywVdcduwqaQonpbTAGjjSh5kcLeCj5MTjYooa9ve2Npx6ho/1/*)#g73kgtdn";
22+
const DESC_4: &str = "tr([5bc5d243/86'/1'/0']tpubDC72NVP1RK5qwy2QdEfWphDsUBAfBu7oiV6jEFooHP8tGQGFVUeFxhgZxuk1j6EQRJ1YsS3th2RyDgReRqCL4zqp4jtuV2z7gbiqDH2iyUS/42/42)";
23+
const DESC_5: &str = "sh(wpkh([5bc5d243/49'/1'/0']tpubDDd6eupua2nhRp2egUAgYGjkxHeh5jPrBDaKLExeySwRvUb1hU7s8osoeACRhXs2w1UGZSMmEpZ1FkjYJ2Pxvfsy7w6XRqYYW7Vw89Unrzr/0/*))#svvvc6el";
24+
25+
fn main() {
26+
let keychain_1 = KeychainId {
27+
number: 1,
28+
nickname: "Johnny's favorite keychain",
29+
script_type: DescriptorType::Tr,
30+
color: Color::Blue,
31+
time_of_week_keychain: DayType::WeekDay,
32+
};
33+
let keychain_2 = KeychainId {
34+
number: 2,
35+
nickname: "Johnny's party keychain",
36+
script_type: DescriptorType::Wpkh,
37+
color: Color::Green,
38+
time_of_week_keychain: DayType::WeekEnd,
39+
};
40+
let keychain_3 = KeychainId {
41+
number: 3,
42+
nickname: "Johnny's old P2PKH keychain",
43+
script_type: DescriptorType::Pkh,
44+
color: Color::Blue,
45+
time_of_week_keychain: DayType::AnyDay,
46+
};
47+
let keychain_4 = KeychainId {
48+
number: 4,
49+
nickname: "Johnny's project donations keychain",
50+
script_type: DescriptorType::Tr,
51+
color: Color::Yellow,
52+
time_of_week_keychain: DayType::AnyDay,
53+
};
54+
let keychain_5 = KeychainId {
55+
number: 5,
56+
nickname: "The secret keychain",
57+
script_type: DescriptorType::ShWpkh,
58+
color: Color::Blue,
59+
time_of_week_keychain: DayType::AnyDay,
60+
};
61+
62+
let mut keyring: KeyRing<KeychainId> = KeyRing::new(Network::Signet, keychain_1, DESC_1);
63+
keyring.add_descriptor(keychain_2, DESC_2, false);
64+
keyring.add_descriptor(keychain_3, DESC_3, false);
65+
keyring.add_descriptor(keychain_4, DESC_4, false);
66+
keyring.add_descriptor(keychain_5, DESC_5, false);
67+
68+
// DESC_1 is the default keychain (the first one added to the keyring is automatically the
69+
// default keychain), but this can also be changed later on with the
70+
// KeyRing::set_default_keychain API. This default keychain is useful because you can use
71+
// APIs like `Wallet::reveal_next_default_address()` which will always work with your
72+
// default keychain.
73+
74+
let mut wallet = Wallet::new(keyring);
75+
76+
let address1 = wallet.reveal_next_default_address();
77+
println!("Default keychain address: {}", address1.address);
78+
79+
let party_address = wallet.reveal_next_address(keychain_2).unwrap();
80+
println!("Party address: {}", party_address.address);
81+
82+
let donation_address = wallet.reveal_next_address(keychain_4).unwrap();
83+
println!("Donation address: {}", donation_address.address);
84+
}
85+
86+
#[derive(Debug, Clone, Copy)]
87+
struct KeychainId {
88+
number: u32,
89+
nickname: &'static str,
90+
script_type: DescriptorType,
91+
color: Color,
92+
time_of_week_keychain: DayType,
93+
}
94+
95+
impl PartialEq for KeychainId {
96+
fn eq(&self, other: &Self) -> bool {
97+
self.number == other.number
98+
}
99+
}
100+
101+
impl Eq for KeychainId {}
102+
103+
impl PartialOrd for KeychainId {
104+
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
105+
Some(self.cmp(other))
106+
}
107+
}
108+
109+
impl Ord for KeychainId {
110+
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
111+
self.number.cmp(&other.number)
112+
}
113+
}
114+
115+
#[derive(Debug, Clone, Copy)]
116+
enum Color {
117+
Blue,
118+
Green,
119+
Yellow,
120+
}
121+
122+
#[derive(Debug, Clone, Copy)]
123+
enum DayType {
124+
AnyDay,
125+
WeekDay,
126+
WeekEnd,
127+
}

0 commit comments

Comments
 (0)