11//! Multi-wallet manager with SPV coordination.
22
3- use std:: collections:: BTreeMap ;
43use std:: sync:: Arc ;
54
65use tokio:: sync:: { broadcast, RwLock } ;
76
87use key_wallet:: wallet:: initialization:: WalletAccountCreationOptions ;
98use key_wallet:: Network ;
9+ use key_wallet_manager:: WalletManager ;
1010
1111use crate :: changeset:: { Merge , PlatformWalletPersistence } ;
1212
@@ -23,8 +23,10 @@ pub struct WalletCreationOptions {
2323use crate :: error:: PlatformWalletError ;
2424use crate :: events:: PlatformWalletEvent ;
2525use crate :: spv:: SpvRuntime ;
26- use crate :: wallet:: platform_wallet:: WalletId ;
26+ use crate :: wallet:: persister:: PlatformWalletPersisterBridge ;
27+ use crate :: wallet:: platform_wallet:: { PlatformWalletInfo , WalletId } ;
2728use crate :: wallet:: PlatformWallet ;
29+ use crate :: wallet:: core:: WalletBalance ;
2830
2931/// Multi-wallet coordinator with SPV sync and event broadcasting.
3032///
@@ -34,13 +36,20 @@ use crate::wallet::PlatformWallet;
3436/// broadcasts unified [`PlatformWalletEvent`]s (sync progress, network
3537/// changes, wallet updates, finality proofs) to subscribers.
3638///
37- /// Each managed [`PlatformWallet`] shares its underlying `Wallet` and
38- /// `ManagedWalletInfo` with the SPV adapter through `Arc<RwLock<…>>`,
39- /// so balance and UTXO updates from SPV are immediately visible to all
40- /// wallet operations.
39+ /// Internally holds a `WalletManager<PlatformWalletInfo>` that implements
40+ /// `WalletInterface` for DashSpvClient, and a separate map of
41+ /// `PlatformWallet` handles. Both share the same `Arc<RwLock<PlatformWalletInfo>>`
42+ /// per wallet, so balance and UTXO updates from SPV are immediately visible
43+ /// to all wallet operations.
4144pub struct PlatformWalletManager {
4245 sdk : Arc < dash_sdk:: Sdk > ,
43- wallets : Arc < RwLock < BTreeMap < WalletId , Arc < PlatformWallet > > > > ,
46+ /// Core-layer wallet manager implementing `WalletInterface`.
47+ /// Shared with `SpvRuntime` so DashSpvClient drives block/mempool
48+ /// processing directly through it.
49+ wallet_manager : Arc < RwLock < WalletManager < PlatformWalletInfo > > > ,
50+ /// Platform-level wallet handles (sub-wallets, identity, dashpay, etc.).
51+ /// Interior mutability via `RwLock` so methods take `&self`.
52+ wallets : RwLock < std:: collections:: BTreeMap < WalletId , Arc < PlatformWallet > > > ,
4453 event_tx : broadcast:: Sender < PlatformWalletEvent > ,
4554 spv : Arc < SpvRuntime > ,
4655 persister : Arc < dyn PlatformWalletPersistence > ,
@@ -50,11 +59,15 @@ impl PlatformWalletManager {
5059 /// Create a new PlatformWalletManager.
5160 pub fn new ( sdk : Arc < dash_sdk:: Sdk > , persister : Arc < dyn PlatformWalletPersistence > ) -> Self {
5261 let ( event_tx, _) = broadcast:: channel ( 256 ) ;
53- let wallets = Arc :: new ( RwLock :: new ( BTreeMap :: new ( ) ) ) ;
54- let spv = Arc :: new ( SpvRuntime :: new ( Arc :: clone ( & wallets) , event_tx. clone ( ) ) ) ;
62+ let wallet_manager = Arc :: new ( RwLock :: new ( WalletManager :: new ( sdk. network ) ) ) ;
63+ let spv = Arc :: new ( SpvRuntime :: new (
64+ Arc :: clone ( & wallet_manager) ,
65+ event_tx. clone ( ) ,
66+ ) ) ;
5567 Self {
5668 sdk,
57- wallets,
69+ wallet_manager,
70+ wallets : RwLock :: new ( std:: collections:: BTreeMap :: new ( ) ) ,
5871 event_tx,
5972 spv,
6073 persister,
@@ -98,9 +111,9 @@ impl PlatformWalletManager {
98111 seed_bytes : [ u8 ; 64 ] ,
99112 options : WalletCreationOptions ,
100113 ) -> Result < Arc < PlatformWallet > , PlatformWalletError > {
101- use key_wallet:: wallet:: managed_wallet_info:: wallet_info_interface:: WalletInfoInterface ;
102114 use key_wallet:: wallet:: managed_wallet_info:: ManagedWalletInfo ;
103115 use key_wallet:: wallet:: Wallet ;
116+ use key_wallet_manager:: ManagedWalletState ;
104117
105118 let wallet =
106119 Wallet :: from_seed_bytes ( seed_bytes, network, options. accounts ) . map_err ( |e| {
@@ -115,11 +128,40 @@ impl PlatformWalletManager {
115128 }
116129 let wallet_id = wallet_info. wallet_id ;
117130
131+ // Build ManagedWalletState with the persister bridge.
132+ let bridge = PlatformWalletPersisterBridge :: new ( wallet_id, Arc :: clone ( & self . persister ) ) ;
133+ let managed_state = ManagedWalletState :: new ( wallet, wallet_info, bridge) ;
134+ let balance = Arc :: new ( WalletBalance :: new ( ) ) ;
135+
136+ // Build the shared state Arc.
137+ let state = Arc :: new ( RwLock :: new ( PlatformWalletInfo {
138+ managed_state,
139+ balance : Arc :: clone ( & balance) ,
140+ identity_manager : crate :: wallet:: identity:: IdentityManager :: new ( ) ,
141+ tracked_asset_locks : std:: collections:: BTreeMap :: new ( ) ,
142+ platform_address_balances : std:: collections:: BTreeMap :: new ( ) ,
143+ token_watched : std:: collections:: BTreeMap :: new ( ) ,
144+ token_balances : std:: collections:: BTreeMap :: new ( ) ,
145+ } ) ) ;
146+
147+ // Insert into WalletManager (shares the same Arc).
148+ {
149+ let mut wm = self . wallet_manager . write ( ) . await ;
150+ wm. insert_wallet_state ( wallet_id, Arc :: clone ( & state) )
151+ . map_err ( |e| {
152+ PlatformWalletError :: WalletCreation ( format ! (
153+ "Failed to register wallet in WalletManager: {}" ,
154+ e
155+ ) )
156+ } ) ?;
157+ }
158+
159+ // Build the PlatformWallet handle from the shared state.
118160 let broadcaster = Arc :: new ( crate :: broadcaster:: SpvBroadcaster :: new ( Arc :: clone ( & self . spv ) ) ) ;
119- let platform_wallet = PlatformWallet :: new (
161+ let platform_wallet = PlatformWallet :: from_shared_state (
120162 Arc :: clone ( & self . sdk ) ,
121- wallet ,
122- wallet_info ,
163+ wallet_id ,
164+ state ,
123165 self . event_tx . clone ( ) ,
124166 Arc :: clone ( & self . persister ) ,
125167 broadcaster,
@@ -134,19 +176,15 @@ impl PlatformWalletManager {
134176 } ) ?;
135177 if !changeset. is_empty ( ) {
136178 platform_wallet. apply ( & changeset) ;
137- // TODO: Once apply() actually restores wallet state (transactions,
138- // UTXOs) from the changeset, set birth_height from the persisted
139- // chain height here so SPV doesn't rescan from genesis on restart.
140- // Until then, birth_height must come from WalletCreationOptions.
141179 }
142180
143181 let platform_wallet = Arc :: new ( platform_wallet) ;
144182
145- // Register with the manager so SPV processes this wallet .
146- let mut wallets = self . wallets . write ( ) . await ;
147- wallets. insert ( wallet_id , Arc :: clone ( & platform_wallet ) ) ;
148- drop ( wallets) ;
149- self . spv . notify_wallets_changed ( ) ;
183+ // Register the PlatformWallet handle .
184+ {
185+ let mut wallets = self . wallets . write ( ) . await ;
186+ wallets. insert ( wallet_id , Arc :: clone ( & platform_wallet ) ) ;
187+ }
150188
151189 Ok ( platform_wallet)
152190 }
@@ -156,11 +194,18 @@ impl PlatformWalletManager {
156194 & self ,
157195 wallet_id : & WalletId ,
158196 ) -> Result < Arc < PlatformWallet > , PlatformWalletError > {
159- let mut wallets = self . wallets . write ( ) . await ;
160- let removed = wallets
161- . remove ( wallet_id)
162- . ok_or_else ( || PlatformWalletError :: WalletNotFound ( hex:: encode ( wallet_id) ) ) ?;
163- self . spv . notify_wallets_changed ( ) ;
197+ // Remove from PlatformWallet handles.
198+ let removed = {
199+ let mut wallets = self . wallets . write ( ) . await ;
200+ wallets
201+ . remove ( wallet_id)
202+ . ok_or_else ( || PlatformWalletError :: WalletNotFound ( hex:: encode ( wallet_id) ) ) ?
203+ } ;
204+ // Remove from WalletManager.
205+ {
206+ let mut wm = self . wallet_manager . write ( ) . await ;
207+ let _ = wm. remove_wallet ( wallet_id) ;
208+ }
164209 Ok ( removed)
165210 }
166211
0 commit comments