Skip to content

Commit 16d6f8c

Browse files
docs: add complex multi-keychain example
1 parent 29fd25c commit 16d6f8c

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+
use bdk_wallet::keyring::KeyRing;
2+
use bdk_wallet::Wallet;
3+
use bitcoin::Network;
4+
use miniscript::descriptor::DescriptorType;
5+
6+
// The KeyRing holds a map of keychain identifiers (`K`) to public descriptors. These keychain
7+
// identifiers can be simple (something like the `DescriptorId` or the `KeychainKind` types work
8+
// well, e.g. see the `simple_keyring.rs` example), but they can also be more complex if required by
9+
// the application. This example shows how the keychain identifier can be used to carry metadata
10+
// about the descriptors, which could be used to select which keychain to use in different scenarios
11+
// when calling methods like `Wallet::reveal_next_address`.
12+
13+
// In this example, Johnny has a lot of keychains he keeps track of in his wallet. The map of
14+
// KeychainIdentifier -> Descriptor uses keys that are custom-made at the application layer, and
15+
// useful for its business logic (for example, choose a weekend keychain when Johnny is out partying
16+
// on the weekend).
17+
18+
const DESC_1: &str = "tr([5bc5d243/86'/1'/0']tpubDC72NVP1RK5qwy2QdEfWphDsUBAfBu7oiV6jEFooHP8tGQGFVUeFxhgZxuk1j6EQRJ1YsS3th2RyDgReRqCL4zqp4jtuV2z7gbiqDH2iyUS/0/*)#xh44xwsp";
19+
const DESC_2: &str = "wpkh([5bc5d243/84'/1'/0']tpubDCA4DcMLVSDifbfUxyJaVVAx57ztsVjke6DRYF95jFFgJqvzA9oENovVd7n34NNURmZxFNRB1VLGyDEqxvaZNXie3ZroEGFbeTS2xLYuaN1/0/*)#q8afsa3z";
20+
const DESC_3: &str = "pkh([5bc5d243/44'/1'/0']tpubDDNQtvd8Sg1mXtSGtxRWEcgg7PbPwUSAyAmBonDSL3HLuutthe54Yih4XDYcywVdcduwqaQonpbTAGjjSh5kcLeCj5MTjYooa9ve2Npx6ho/1/*)#g73kgtdn";
21+
const DESC_4: &str = "tr([5bc5d243/86'/1'/0']tpubDC72NVP1RK5qwy2QdEfWphDsUBAfBu7oiV6jEFooHP8tGQGFVUeFxhgZxuk1j6EQRJ1YsS3th2RyDgReRqCL4zqp4jtuV2z7gbiqDH2iyUS/42/42)";
22+
const DESC_5: &str = "sh(wpkh([5bc5d243/49'/1'/0']tpubDDd6eupua2nhRp2egUAgYGjkxHeh5jPrBDaKLExeySwRvUb1hU7s8osoeACRhXs2w1UGZSMmEpZ1FkjYJ2Pxvfsy7w6XRqYYW7Vw89Unrzr/0/*))#svvvc6el";
23+
24+
fn main() {
25+
let keychain_1 = KeychainId {
26+
number: 1,
27+
nickname: "Johnny's favorite keychain",
28+
script_type: DescriptorType::Tr,
29+
color: Color::Blue,
30+
time_of_week_keychain: DayType::WeekDay,
31+
};
32+
let keychain_2 = KeychainId {
33+
number: 2,
34+
nickname: "Johnny's party keychain",
35+
script_type: DescriptorType::Wpkh,
36+
color: Color::Green,
37+
time_of_week_keychain: DayType::WeekEnd,
38+
};
39+
let keychain_3 = KeychainId {
40+
number: 3,
41+
nickname: "Johnny's old P2PKH keychain",
42+
script_type: DescriptorType::Pkh,
43+
color: Color::Blue,
44+
time_of_week_keychain: DayType::AnyDay,
45+
};
46+
let keychain_4 = KeychainId {
47+
number: 4,
48+
nickname: "Johnny's project donations keychain",
49+
script_type: DescriptorType::Tr,
50+
color: Color::Yellow,
51+
time_of_week_keychain: DayType::AnyDay,
52+
};
53+
let keychain_5 = KeychainId {
54+
number: 5,
55+
nickname: "The secret keychain",
56+
script_type: DescriptorType::ShWpkh,
57+
color: Color::Blue,
58+
time_of_week_keychain: DayType::AnyDay,
59+
};
60+
61+
let mut keyring: KeyRing<KeychainId> = KeyRing::new(Network::Signet, keychain_1, DESC_1);
62+
keyring.add_descriptor(keychain_2, DESC_2, false);
63+
keyring.add_descriptor(keychain_3, DESC_3, false);
64+
keyring.add_descriptor(keychain_4, DESC_4, false);
65+
keyring.add_descriptor(keychain_5, DESC_5, false);
66+
67+
// DESC_1 is the default keychain (the first one added to the keyring is automatically the
68+
// default keychain), but this can also be changed later on with the
69+
// KeyRing::set_default_keychain API. This default keychain is useful because you can use
70+
// APIs like `Wallet::reveal_next_default_address()` which will always work with your
71+
// default keychain.
72+
73+
let mut wallet = Wallet::new(keyring);
74+
75+
let address1 = wallet.reveal_next_default_address();
76+
println!("Default keychain address: {}", address1.address);
77+
78+
let party_address = wallet.reveal_next_address(keychain_2).unwrap();
79+
println!("Party address: {}", party_address.address);
80+
81+
let donation_address = wallet.reveal_next_address(keychain_4).unwrap();
82+
println!("Donation address: {}", donation_address.address);
83+
}
84+
85+
#[allow(dead_code)]
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)