@@ -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