Skip to content

Commit ac4c44f

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

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed

examples/multi_keychain_wallet.rs

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

0 commit comments

Comments
 (0)