Skip to content

Commit bed270d

Browse files
committed
feat(wallet): add get_keymap() helper and sign_psbt doc example
1 parent d266142 commit bed270d

1 file changed

Lines changed: 57 additions & 0 deletions

File tree

src/wallet/mod.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,6 +1853,17 @@ impl Wallet {
18531853
}
18541854
}
18551855

1856+
/// Returns a combined [`KeyMap`] from all signing keys loaded in the wallet.
1857+
///
1858+
/// The map merges keys from both the external (receive) and internal (change) keychains.
1859+
/// It can be used with [`miniscript::descriptor::KeyMapWrapper`] to sign a PSBT via [`Wallet::sign_psbt`] using
1860+
/// the wallet's own keys.
1861+
pub fn get_keymap(&self) -> KeyMap {
1862+
let mut keymap = self.signers.as_key_map(&self.secp);
1863+
keymap.extend(self.change_signers.as_key_map(&self.secp));
1864+
keymap
1865+
}
1866+
18561867
/// Sign a PSBT using an external key provider via [`bitcoin::Psbt::sign`].
18571868
///
18581869
/// This is a thin wrapper around [`bitcoin::Psbt::sign`] that supplies the wallet's
@@ -1867,6 +1878,23 @@ impl Wallet {
18671878
/// the correct child keys. PSBTs received from external coordinator tools or
18681879
/// hardware wallet flows typically carry this metadata already.
18691880
///
1881+
/// # Signing with the wallet's own keys
1882+
///
1883+
/// Use [`Wallet::get_keymap`] together with [`miniscript::descriptor::KeyMapWrapper`] to sign with the keys
1884+
/// already loaded in the wallet:
1885+
///
1886+
/// ```rust,no_run
1887+
/// # use bdk_wallet::Wallet;
1888+
/// # use bdk_wallet::bitcoin::Psbt;
1889+
/// # use miniscript::descriptor::KeyMapWrapper;
1890+
/// # fn example(wallet: &Wallet, psbt: &mut Psbt) -> Result<(), Box<dyn std::error::Error>> {
1891+
/// let keymap = wallet.get_keymap();
1892+
/// let wrapper = KeyMapWrapper::from(keymap);
1893+
/// wallet.sign_psbt(psbt, &wrapper).map_err(|(_, e)| format!("{e:?}"))?;
1894+
/// # Ok(())
1895+
/// # }
1896+
/// ```
1897+
///
18701898
/// # Returns
18711899
///
18721900
/// On success, a [`psbt::SigningKeysMap`] mapping each signed input index to the keys
@@ -3185,4 +3213,33 @@ mod test {
31853213
let wallet_name = result_with_change.unwrap();
31863214
assert_eq!(wallet_name, "vn4aqs37jgrerlc3");
31873215
}
3216+
3217+
#[test]
3218+
fn test_get_keymap() {
3219+
use crate::test_utils::get_test_wpkh_and_change_desc;
3220+
let (external_desc, internal_desc) = get_test_wpkh_and_change_desc();
3221+
let wallet = Wallet::create(external_desc, internal_desc)
3222+
.network(Network::Testnet)
3223+
.create_wallet_no_persist()
3224+
.unwrap();
3225+
3226+
let keymap = wallet.get_keymap();
3227+
assert!(!keymap.is_empty());
3228+
3229+
let external_keymap = wallet
3230+
.get_signers(KeychainKind::External)
3231+
.as_key_map(wallet.secp_ctx());
3232+
let internal_keymap = wallet
3233+
.get_signers(KeychainKind::Internal)
3234+
.as_key_map(wallet.secp_ctx());
3235+
3236+
assert_eq!(keymap.len(), external_keymap.len() + internal_keymap.len());
3237+
3238+
for (pubkey, _) in external_keymap.iter() {
3239+
assert!(keymap.contains_key(pubkey));
3240+
}
3241+
for (pubkey, _) in internal_keymap.iter() {
3242+
assert!(keymap.contains_key(pubkey));
3243+
}
3244+
}
31883245
}

0 commit comments

Comments
 (0)