@@ -33,6 +33,44 @@ impl<T: WalletInfoInterface + Send + Sync + 'static> WalletManager<T> {
3333 }
3434 }
3535
36+ /// Immutable wallet + mutable info — split borrow on two maps.
37+ pub fn get_wallet_and_info_mut ( & mut self , wallet_id : & WalletId ) -> Option < ( & Wallet , & mut T ) > {
38+ match ( self . wallets . get ( wallet_id) , self . wallet_infos . get_mut ( wallet_id) ) {
39+ ( Some ( wallet) , Some ( info) ) => Some ( ( wallet, info) ) ,
40+ _ => None ,
41+ }
42+ }
43+
44+ /// Mutable wallet + mutable info — split borrow on two maps.
45+ ///
46+ /// Used when the caller needs to mutate both the `Wallet` (e.g. to
47+ /// idempotently re-derive HD accounts via `Wallet::add_account` during
48+ /// changeset replay) and the associated info in the same scope.
49+ pub fn get_wallet_mut_and_info_mut (
50+ & mut self ,
51+ wallet_id : & WalletId ,
52+ ) -> Option < ( & mut Wallet , & mut T ) > {
53+ match ( self . wallets . get_mut ( wallet_id) , self . wallet_infos . get_mut ( wallet_id) ) {
54+ ( Some ( wallet) , Some ( info) ) => Some ( ( wallet, info) ) ,
55+ _ => None ,
56+ }
57+ }
58+
59+ /// Insert a pre-built wallet and info pair.
60+ ///
61+ /// Errors with [`WalletError::WalletExists`] if a wallet with the same ID is
62+ /// already registered. On success bumps the structural revision.
63+ pub fn insert_wallet ( & mut self , wallet : Wallet , info : T ) -> Result < WalletId , WalletError > {
64+ let wallet_id = wallet. compute_wallet_id ( ) ;
65+ if self . wallets . contains_key ( & wallet_id) {
66+ return Err ( WalletError :: WalletExists ( wallet_id) ) ;
67+ }
68+ self . wallets . insert ( wallet_id, wallet) ;
69+ self . wallet_infos . insert ( wallet_id, info) ;
70+ self . bump_structural_revision ( ) ;
71+ Ok ( wallet_id)
72+ }
73+
3674 /// Remove a wallet
3775 pub fn remove_wallet ( & mut self , wallet_id : & WalletId ) -> Result < ( Wallet , T ) , WalletError > {
3876 let wallet =
@@ -192,3 +230,33 @@ impl<T: WalletInfoInterface + Send + Sync + 'static> WalletManager<T> {
192230 outpoints
193231 }
194232}
233+
234+ #[ cfg( test) ]
235+ mod tests {
236+ use super :: * ;
237+ use crate :: test_helpers:: TEST_MNEMONIC ;
238+ use key_wallet:: mnemonic:: { Language , Mnemonic } ;
239+ use key_wallet:: wallet:: initialization:: WalletAccountCreationOptions ;
240+ use key_wallet:: wallet:: managed_wallet_info:: ManagedWalletInfo ;
241+
242+ fn build_wallet ( ) -> Wallet {
243+ let mnemonic = Mnemonic :: from_phrase ( TEST_MNEMONIC , Language :: English ) . unwrap ( ) ;
244+ Wallet :: from_mnemonic ( mnemonic, Network :: Testnet , WalletAccountCreationOptions :: Default )
245+ . expect ( "wallet from mnemonic" )
246+ }
247+
248+ #[ test]
249+ fn insert_wallet_rejects_duplicate ( ) {
250+ let mut manager: WalletManager < ManagedWalletInfo > = WalletManager :: new ( Network :: Testnet ) ;
251+ let wallet = build_wallet ( ) ;
252+ let info = ManagedWalletInfo :: from_wallet ( & wallet) ;
253+
254+ let id =
255+ manager. insert_wallet ( wallet. clone ( ) , info. clone ( ) ) . expect ( "first insert succeeds" ) ;
256+
257+ match manager. insert_wallet ( wallet, info) {
258+ Err ( WalletError :: WalletExists ( dup_id) ) => assert_eq ! ( dup_id, id) ,
259+ other => panic ! ( "expected WalletExists, got {:?}" , other) ,
260+ }
261+ }
262+ }
0 commit comments