Skip to content

Commit 042f5e2

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

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