Skip to content

Commit 7316f44

Browse files
committed
feat: track synced_height per ManagedWalletInfo
1 parent 3884314 commit 7316f44

File tree

9 files changed

+152
-96
lines changed

9 files changed

+152
-96
lines changed

key-wallet-ffi/FFI_API.md

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Functions: 3
4242

4343
### Wallet Manager
4444

45-
Functions: 19
45+
Functions: 18
4646

4747
| Function | Description | Module |
4848
|----------|-------------|--------|
@@ -63,12 +63,11 @@ Functions: 19
6363
| `wallet_manager_get_wallet_ids` | Get wallet IDs # Safety - `manager` must be a valid pointer to an... | wallet_manager |
6464
| `wallet_manager_import_wallet_from_bytes` | No description | wallet_manager |
6565
| `wallet_manager_process_transaction` | Process a transaction through all wallets Checks a transaction against all... | wallet_manager |
66-
| `wallet_manager_update_height` | Update block height for a network # Safety - `manager` must be a valid... | wallet_manager |
6766
| `wallet_manager_wallet_count` | Get wallet count # Safety - `manager` must be a valid pointer to an... | wallet_manager |
6867

6968
### Wallet Operations
7069

71-
Functions: 62
70+
Functions: 63
7271

7372
| Function | Description | Module |
7473
|----------|-------------|--------|
@@ -99,6 +98,7 @@ Functions: 62
9998
| `managed_wallet_info_free` | Free managed wallet info returned by wallet_manager_get_managed_wallet_info ... | managed_wallet |
10099
| `managed_wallet_mark_address_used` | Mark an address as used in the pool This updates the pool's tracking of... | address_pool |
101100
| `managed_wallet_set_gap_limit` | Set the gap limit for an address pool The gap limit determines how many... | address_pool |
101+
| `managed_wallet_synced_height` | Get current synced height from wallet info # Safety - `managed_wallet`... | managed_wallet |
102102
| `wallet_add_account` | Add an account to the wallet without xpub # Safety This function... | wallet |
103103
| `wallet_add_account_with_string_xpub` | Add an account to the wallet with xpub as string # Safety This function... | wallet |
104104
| `wallet_add_account_with_xpub_bytes` | Add an account to the wallet with xpub as byte array # Safety This... | wallet |
@@ -666,22 +666,6 @@ Process a transaction through all wallets Checks a transaction against all wall
666666

667667
---
668668

669-
#### `wallet_manager_update_height`
670-
671-
```c
672-
wallet_manager_update_height(manager: *mut FFIWalletManager, height: c_uint, error: *mut FFIError,) -> bool
673-
```
674-
675-
**Description:**
676-
Update block height for a network # Safety - `manager` must be a valid pointer to an FFIWalletManager - `error` must be a valid pointer to an FFIError structure or null - The caller must ensure all pointers remain valid for the duration of this call
677-
678-
**Safety:**
679-
- `manager` must be a valid pointer to an FFIWalletManager - `error` must be a valid pointer to an FFIError structure or null - The caller must ensure all pointers remain valid for the duration of this call
680-
681-
**Module:** `wallet_manager`
682-
683-
---
684-
685669
#### `wallet_manager_wallet_count`
686670

687671
```c
@@ -1120,6 +1104,22 @@ Set the gap limit for an address pool The gap limit determines how many unused
11201104

11211105
---
11221106

1107+
#### `managed_wallet_synced_height`
1108+
1109+
```c
1110+
managed_wallet_synced_height(managed_wallet: *const FFIManagedWalletInfo, error: *mut FFIError,) -> c_uint
1111+
```
1112+
1113+
**Description:**
1114+
Get current synced height from wallet info # Safety - `managed_wallet` must be a valid pointer to an FFIManagedWalletInfo - `error` must be a valid pointer to an FFIError structure or null - The caller must ensure all pointers remain valid for the duration of this call
1115+
1116+
**Safety:**
1117+
- `managed_wallet` must be a valid pointer to an FFIManagedWalletInfo - `error` must be a valid pointer to an FFIError structure or null - The caller must ensure all pointers remain valid for the duration of this call
1118+
1119+
**Module:** `managed_wallet`
1120+
1121+
---
1122+
11231123
#### `wallet_add_account`
11241124

11251125
```c

key-wallet-ffi/include/key_wallet_ffi.h

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3089,6 +3089,20 @@ bool managed_wallet_get_balance(const FFIManagedWalletInfo *managed_wallet,
30893089
FFIError *error)
30903090
;
30913091

3092+
/*
3093+
Get current synced height from wallet info
3094+
3095+
# Safety
3096+
3097+
- `managed_wallet` must be a valid pointer to an FFIManagedWalletInfo
3098+
- `error` must be a valid pointer to an FFIError structure or null
3099+
- The caller must ensure all pointers remain valid for the duration of this call
3100+
*/
3101+
3102+
unsigned int managed_wallet_synced_height(const FFIManagedWalletInfo *managed_wallet,
3103+
FFIError *error)
3104+
;
3105+
30923106
/*
30933107
Free managed wallet info
30943108
@@ -4087,21 +4101,6 @@ bool wallet_manager_process_transaction(FFIWalletManager *manager,
40874101
FFIError *error)
40884102
;
40894103

4090-
/*
4091-
Update block height for a network
4092-
4093-
# Safety
4094-
4095-
- `manager` must be a valid pointer to an FFIWalletManager
4096-
- `error` must be a valid pointer to an FFIError structure or null
4097-
- The caller must ensure all pointers remain valid for the duration of this call
4098-
*/
4099-
4100-
bool wallet_manager_update_height(FFIWalletManager *manager,
4101-
unsigned int height,
4102-
FFIError *error)
4103-
;
4104-
41054104
/*
41064105
Get current height for a network
41074106

key-wallet-ffi/src/managed_wallet.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
//!
66
77
use std::ffi::CString;
8-
use std::os::raw::c_char;
8+
use std::os::raw::{c_char, c_uint};
99
use std::ptr;
1010

1111
use crate::error::{FFIError, FFIErrorCode};
1212
use crate::types::FFIWallet;
1313
use key_wallet::managed_account::address_pool::KeySource;
14+
use key_wallet::wallet::managed_wallet_info::wallet_info_interface::WalletInfoInterface;
1415
use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo;
1516
use std::ffi::c_void;
1617

@@ -585,6 +586,31 @@ pub unsafe extern "C" fn managed_wallet_get_balance(
585586
true
586587
}
587588

589+
/// Get current synced height from wallet info
590+
///
591+
/// # Safety
592+
///
593+
/// - `managed_wallet` must be a valid pointer to an FFIManagedWalletInfo
594+
/// - `error` must be a valid pointer to an FFIError structure or null
595+
/// - The caller must ensure all pointers remain valid for the duration of this call
596+
#[no_mangle]
597+
pub unsafe extern "C" fn managed_wallet_synced_height(
598+
managed_wallet: *const FFIManagedWalletInfo,
599+
error: *mut FFIError,
600+
) -> c_uint {
601+
if managed_wallet.is_null() {
602+
FFIError::set_error(
603+
error,
604+
FFIErrorCode::InvalidInput,
605+
"Managed wallet is null".to_string(),
606+
);
607+
return 0;
608+
}
609+
let managed_wallet = unsafe { &*managed_wallet };
610+
FFIError::set_success(error);
611+
managed_wallet.inner().synced_height()
612+
}
613+
588614
/// Free managed wallet info
589615
///
590616
/// # Safety

key-wallet-ffi/src/wallet_manager.rs

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -775,35 +775,6 @@ pub unsafe extern "C" fn wallet_manager_process_transaction(
775775
!relevant_wallets.is_empty()
776776
}
777777

778-
/// Update block height for a network
779-
///
780-
/// # Safety
781-
///
782-
/// - `manager` must be a valid pointer to an FFIWalletManager
783-
/// - `error` must be a valid pointer to an FFIError structure or null
784-
/// - The caller must ensure all pointers remain valid for the duration of this call
785-
#[no_mangle]
786-
pub unsafe extern "C" fn wallet_manager_update_height(
787-
manager: *mut FFIWalletManager,
788-
height: c_uint,
789-
error: *mut FFIError,
790-
) -> bool {
791-
if manager.is_null() {
792-
FFIError::set_error(error, FFIErrorCode::InvalidInput, "Manager is null".to_string());
793-
return false;
794-
}
795-
796-
let manager_ref = &*manager;
797-
798-
manager_ref.runtime.block_on(async {
799-
let mut manager_guard = manager_ref.manager.write().await;
800-
manager_guard.update_height(height);
801-
});
802-
803-
FFIError::set_success(error);
804-
true
805-
}
806-
807778
/// Get current height for a network
808779
///
809780
/// # Safety

key-wallet-ffi/src/wallet_manager_tests.rs

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -207,33 +207,6 @@ mod tests {
207207
}
208208
}
209209

210-
#[test]
211-
fn test_height_management() {
212-
let mut error = FFIError::success();
213-
let error = &mut error as *mut FFIError;
214-
215-
let manager = wallet_manager::wallet_manager_create(FFINetwork::Testnet, error);
216-
assert!(!manager.is_null());
217-
218-
// Get initial height
219-
let height = unsafe { wallet_manager::wallet_manager_current_height(manager, error) };
220-
assert_eq!(height, 0);
221-
222-
// Update height
223-
let success =
224-
unsafe { wallet_manager::wallet_manager_update_height(manager, 100000, error) };
225-
assert!(success);
226-
227-
// Verify height was updated
228-
let height = unsafe { wallet_manager::wallet_manager_current_height(manager, error) };
229-
assert_eq!(height, 100000);
230-
231-
// Clean up
232-
unsafe {
233-
wallet_manager::wallet_manager_free(manager);
234-
}
235-
}
236-
237210
#[test]
238211
fn test_error_handling() {
239212
let mut error = FFIError::success();
@@ -465,20 +438,25 @@ mod tests {
465438
}
466439

467440
#[test]
468-
fn test_wallet_manager_height_operations() {
441+
fn test_wallet_manager_current_height() {
469442
let mut error = FFIError::success();
470443
let error = &mut error as *mut FFIError;
471444

472445
let manager = wallet_manager::wallet_manager_create(FFINetwork::Testnet, error);
473446
assert!(!manager.is_null());
474447

475448
// Get initial height
476-
let _height = unsafe { wallet_manager::wallet_manager_current_height(manager, error) };
449+
let height = unsafe { wallet_manager::wallet_manager_current_height(manager, error) };
450+
assert_eq!(height, 0);
477451

478452
// Update height
479453
let new_height = 12345;
480454
unsafe {
481-
wallet_manager::wallet_manager_update_height(manager, new_height, error);
455+
let manager_ref = &*manager;
456+
manager_ref.runtime.block_on(async {
457+
let mut manager_guard = manager_ref.manager.write().await;
458+
manager_guard.update_height(new_height);
459+
});
482460
}
483461

484462
// Get updated height

key-wallet-manager/src/wallet_manager/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -930,9 +930,12 @@ impl<T: WalletInfoInterface> WalletManager<T> {
930930
self.current_height
931931
}
932932

933-
/// Update current block height for a specific network
933+
/// Update current block height and propagate to all wallet infos
934934
pub fn update_height(&mut self, height: u32) {
935-
self.current_height = height
935+
self.current_height = height;
936+
for info in self.wallet_infos.values_mut() {
937+
info.update_chain_height(height);
938+
}
936939
}
937940

938941
/// Get monitored addresses for all wallets for a specific network

key-wallet-manager/tests/integration_test.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
66
use key_wallet::wallet::initialization::WalletAccountCreationOptions;
77
use key_wallet::wallet::managed_wallet_info::transaction_building::AccountTypePreference;
8+
use key_wallet::wallet::managed_wallet_info::wallet_info_interface::WalletInfoInterface;
89
use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo;
910
use key_wallet::{mnemonic::Language, Mnemonic, Network};
1011
use key_wallet_manager::wallet_manager::{WalletError, WalletManager};
@@ -155,8 +156,75 @@ fn test_balance_calculation() {
155156
fn test_block_height_tracking() {
156157
let mut manager = WalletManager::<ManagedWalletInfo>::new(Network::Testnet);
157158

159+
// Initial state
158160
assert_eq!(manager.current_height(), 0);
159161

162+
// Set height before adding wallets
163+
manager.update_height(1000);
164+
assert_eq!(manager.current_height(), 1000);
165+
166+
let mnemonic1 = Mnemonic::generate(12, Language::English).unwrap();
167+
let wallet_id1 = manager
168+
.create_wallet_from_mnemonic(
169+
&mnemonic1.to_string(),
170+
"",
171+
0,
172+
WalletAccountCreationOptions::Default,
173+
)
174+
.unwrap();
175+
176+
let mnemonic2 = Mnemonic::generate(12, Language::English).unwrap();
177+
let wallet_id2 = manager
178+
.create_wallet_from_mnemonic(
179+
&mnemonic2.to_string(),
180+
"",
181+
0,
182+
WalletAccountCreationOptions::Default,
183+
)
184+
.unwrap();
185+
186+
assert_eq!(manager.wallet_count(), 2);
187+
188+
// Verify both wallets have synced_height of 0 initially
189+
for wallet_info in manager.get_all_wallet_infos().values() {
190+
assert_eq!(wallet_info.synced_height(), 0);
191+
}
192+
193+
// Update height - should propagate to all wallets
160194
manager.update_height(12345);
161195
assert_eq!(manager.current_height(), 12345);
196+
197+
// Verify all wallets got updated
198+
let wallet_info1 = manager.get_wallet_info(&wallet_id1).unwrap();
199+
let wallet_info2 = manager.get_wallet_info(&wallet_id2).unwrap();
200+
assert_eq!(wallet_info1.synced_height(), 12345);
201+
assert_eq!(wallet_info2.synced_height(), 12345);
202+
203+
// Update again - verify subsequent updates work
204+
manager.update_height(20000);
205+
assert_eq!(manager.current_height(), 20000);
206+
207+
for wallet_info in manager.get_all_wallet_infos().values() {
208+
assert_eq!(wallet_info.synced_height(), 20000);
209+
}
210+
211+
// Update wallets individually to different heights
212+
let wallet_info1 = manager.get_wallet_info_mut(&wallet_id1).unwrap();
213+
wallet_info1.update_chain_height(30000);
214+
215+
let wallet_info2 = manager.get_wallet_info_mut(&wallet_id2).unwrap();
216+
wallet_info2.update_chain_height(25000);
217+
218+
// Verify each wallet has its own synced_height
219+
let wallet_info1 = manager.get_wallet_info(&wallet_id1).unwrap();
220+
let wallet_info2 = manager.get_wallet_info(&wallet_id2).unwrap();
221+
assert_eq!(wallet_info1.synced_height(), 30000);
222+
assert_eq!(wallet_info2.synced_height(), 25000);
223+
224+
// Manager update_height still syncs all wallets
225+
manager.update_height(40000);
226+
let wallet_info1 = manager.get_wallet_info(&wallet_id1).unwrap();
227+
let wallet_info2 = manager.get_wallet_info(&wallet_id2).unwrap();
228+
assert_eq!(wallet_info1.synced_height(), 40000);
229+
assert_eq!(wallet_info2.synced_height(), 40000);
162230
}

key-wallet/src/wallet/managed_wallet_info/wallet_info_interface.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ pub trait WalletInfoInterface: Sized + WalletTransactionChecker + ManagedAccount
6161
/// Update last synced timestamp
6262
fn update_last_synced(&mut self, timestamp: u64);
6363

64+
/// Get the synced height
65+
fn synced_height(&self) -> CoreBlockHeight;
66+
6467
/// Get all monitored addresses
6568
fn monitored_addresses(&self) -> Vec<DashAddress>;
6669

@@ -156,6 +159,10 @@ impl WalletInfoInterface for ManagedWalletInfo {
156159
self.metadata.birth_height = height;
157160
}
158161

162+
fn synced_height(&self) -> CoreBlockHeight {
163+
self.metadata.synced_height
164+
}
165+
159166
fn first_loaded_at(&self) -> u64 {
160167
self.metadata.first_loaded_at
161168
}
@@ -323,6 +330,8 @@ impl WalletInfoInterface for ManagedWalletInfo {
323330
}
324331

325332
fn update_chain_height(&mut self, current_height: u32) {
333+
self.metadata.synced_height = current_height;
334+
326335
let matured = self.process_matured_transactions(current_height);
327336

328337
if !matured.is_empty() {

0 commit comments

Comments
 (0)