Skip to content

Commit 9f46c08

Browse files
committed
feat: add api to create keyring with multiple desc
1 parent d1d8c74 commit 9f46c08

File tree

3 files changed

+65
-14
lines changed

3 files changed

+65
-14
lines changed

examples/multi_keychain_wallet.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::collections::BTreeMap;
2+
13
use bdk_wallet::keyring::KeyRing;
24
use bdk_wallet::Wallet;
35
use bitcoin::Network;
@@ -58,12 +60,16 @@ fn main() {
5860
time_of_week_keychain: DayType::AnyDay,
5961
};
6062

61-
let mut keyring: KeyRing<KeychainId> =
62-
KeyRing::new(Network::Signet, keychain_1, DESC_1).unwrap();
63-
keyring.add_descriptor(keychain_2, DESC_2, false).unwrap();
64-
keyring.add_descriptor(keychain_3, DESC_3, false).unwrap();
65-
keyring.add_descriptor(keychain_4, DESC_4, false).unwrap();
66-
keyring.add_descriptor(keychain_5, DESC_5, false).unwrap();
63+
let descriptors: BTreeMap<KeychainId, &str> = [
64+
(keychain_1, DESC_1),
65+
(keychain_2, DESC_2),
66+
(keychain_3, DESC_3),
67+
(keychain_4, DESC_4),
68+
(keychain_5, DESC_5),
69+
]
70+
.into();
71+
72+
let keyring = KeyRing::new_with_descriptors(Network::Signet, descriptors, None).unwrap();
6773

6874
// DESC_1 is the default keychain (the first one added to the keyring is automatically the
6975
// default keychain), but this can also be changed later on with the

src/keyring/mod.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,44 @@ where
6666
})
6767
}
6868

69+
/// Construct a new [`KeyRing`] with the provided `network` and a <Keychain, Descriptor> map and
70+
/// the `default_keychain`.
71+
///
72+
/// Specifying `default_keychain` as `None` will assign the first keychain according to the
73+
/// `Ord` implementation as the default.
74+
///
75+
/// Uses [`KeyRing::new`] and [`KeyRing::add_descriptor`] underneath.
76+
pub fn new_with_descriptors<D: IntoWalletDescriptor>(
77+
network: Network,
78+
descriptors: BTreeMap<K, D>,
79+
default_keychain: Option<K>,
80+
) -> Result<Self, DescriptorError> {
81+
// ToDo: maybe we can use something more generic than a map?
82+
// ToDo: handle error
83+
if descriptors.is_empty() {
84+
panic!()
85+
};
86+
87+
let mut desc_iter = descriptors.into_iter();
88+
let (keychain, desc) = desc_iter.next().expect("descriptors is non-empty");
89+
let mut keyring = KeyRing::new(network, keychain.clone(), desc)?;
90+
91+
let curr_default = match default_keychain {
92+
Some(curr_default) => curr_default,
93+
None => keychain,
94+
};
95+
96+
for (keychain, desc) in desc_iter {
97+
let mut default = false;
98+
if curr_default == keychain {
99+
default = true;
100+
}
101+
keyring.add_descriptor(keychain, desc, default)?;
102+
}
103+
104+
Ok(keyring)
105+
}
106+
69107
/// Get the [`Network`] corresponding to the [`KeyRing`]
70108
pub fn network(&self) -> &Network {
71109
&self.network

tests/keyring.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::collections::BTreeMap;
2+
13
use bdk_wallet::chain::DescriptorExt;
24
use bdk_wallet::descriptor::DescriptorError;
35
use bdk_wallet::keyring::{self, KeyRing};
@@ -38,14 +40,19 @@ fn test_8_keychains_keyring() {
3840
const DESC_7: &str = "tr(tprv8ZgxMBicQKsPdWAHbugK2tjtVtRjKGixYVZUdL7xLHMgXZS6BFbFi1UDb1CHT25Z5PU1F9j7wGxwUiRhqz9E3nZRztikGUV6HoRDYcqPhM4/86'/1'/0'/6/*)";
3941
const DESC_8: &str = "tr(tprv8ZgxMBicQKsPdWAHbugK2tjtVtRjKGixYVZUdL7xLHMgXZS6BFbFi1UDb1CHT25Z5PU1F9j7wGxwUiRhqz9E3nZRztikGUV6HoRDYcqPhM4/86'/1'/0'/7/*)";
4042

41-
let mut keyring = KeyRing::new(Network::Regtest, 1, DESC_1).unwrap();
42-
keyring.add_descriptor(2, DESC_2, false).unwrap();
43-
keyring.add_descriptor(3, DESC_3, false).unwrap();
44-
keyring.add_descriptor(4, DESC_4, false).unwrap();
45-
keyring.add_descriptor(5, DESC_5, false).unwrap();
46-
keyring.add_descriptor(6, DESC_6, false).unwrap();
47-
keyring.add_descriptor(7, DESC_7, false).unwrap();
48-
keyring.add_descriptor(8, DESC_8, false).unwrap();
43+
let descriptors: BTreeMap<u8, &str> = [
44+
(1, DESC_1),
45+
(2, DESC_2),
46+
(3, DESC_3),
47+
(4, DESC_4),
48+
(5, DESC_5),
49+
(6, DESC_6),
50+
(7, DESC_7),
51+
(8, DESC_8),
52+
]
53+
.into();
54+
55+
let keyring = KeyRing::new_with_descriptors(Network::Regtest, descriptors, Some(1)).unwrap();
4956

5057
assert_eq!(keyring.default_keychain(), 1);
5158
assert_eq!(keyring.list_keychains().len(), 8);

0 commit comments

Comments
 (0)