Skip to content

Commit 9134ce2

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

File tree

1 file changed

+128
-0
lines changed

1 file changed

+128
-0
lines changed

examples/multi_keychain_wallet.rs

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
use bitcoin::Network;
2+
use miniscript::descriptor::DescriptorType;
3+
use bdk_wallet::keyring::KeyRing;
4+
use bdk_wallet::Wallet;
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 KeyRing::set_default_keychain
72+
// API. This default keychain is useful because you can use APIs like
73+
// `Wallet::reveal_next_default_address()` which will always work with your default keychain.
74+
75+
let mut wallet = Wallet::new(keyring);
76+
77+
let address1 = wallet.reveal_next_default_address();
78+
println!("Default keychain address: {}", address1.address);
79+
80+
let party_address = wallet.reveal_next_address(keychain_2).unwrap();
81+
println!("Party address: {}", party_address.address);
82+
83+
let donation_address = wallet.reveal_next_address(keychain_4).unwrap();
84+
println!("Donation address: {}", donation_address.address);
85+
}
86+
87+
#[derive(Debug, Clone, Copy)]
88+
struct KeychainId {
89+
number: u32,
90+
nickname: &'static str,
91+
script_type: DescriptorType,
92+
color: Color,
93+
time_of_week_keychain: DayType,
94+
}
95+
96+
impl PartialEq for KeychainId {
97+
fn eq(&self, other: &Self) -> bool {
98+
self.number == other.number
99+
}
100+
}
101+
102+
impl Eq for KeychainId {}
103+
104+
impl PartialOrd for KeychainId {
105+
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
106+
Some(self.cmp(other))
107+
}
108+
}
109+
110+
impl Ord for KeychainId {
111+
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
112+
self.number.cmp(&other.number)
113+
}
114+
}
115+
116+
#[derive(Debug, Clone, Copy)]
117+
enum Color {
118+
Blue,
119+
Green,
120+
Yellow,
121+
}
122+
123+
#[derive(Debug, Clone, Copy)]
124+
enum DayType {
125+
AnyDay,
126+
WeekDay,
127+
WeekEnd,
128+
}

0 commit comments

Comments
 (0)