Skip to content

Commit 1df1148

Browse files
authored
feat: track synced_height per ManagedWalletInfo (#305)
1 parent 35630ef commit 1df1148

File tree

10 files changed

+155
-100
lines changed

10 files changed

+155
-100
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
@@ -787,35 +787,6 @@ pub unsafe extern "C" fn wallet_manager_process_transaction(
787787
!relevant_wallets.is_empty()
788788
}
789789

790-
/// Update block height for a network
791-
///
792-
/// # Safety
793-
///
794-
/// - `manager` must be a valid pointer to an FFIWalletManager
795-
/// - `error` must be a valid pointer to an FFIError structure or null
796-
/// - The caller must ensure all pointers remain valid for the duration of this call
797-
#[no_mangle]
798-
pub unsafe extern "C" fn wallet_manager_update_height(
799-
manager: *mut FFIWalletManager,
800-
height: c_uint,
801-
error: *mut FFIError,
802-
) -> bool {
803-
if manager.is_null() {
804-
FFIError::set_error(error, FFIErrorCode::InvalidInput, "Manager is null".to_string());
805-
return false;
806-
}
807-
808-
let manager_ref = &*manager;
809-
810-
manager_ref.runtime.block_on(async {
811-
let mut manager_guard = manager_ref.manager.write().await;
812-
manager_guard.update_height(height);
813-
});
814-
815-
FFIError::set_success(error);
816-
true
817-
}
818-
819790
/// Get current height for a network
820791
///
821792
/// # Safety

key-wallet-ffi/src/wallet_manager_tests.rs

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -208,34 +208,6 @@ mod tests {
208208
}
209209
}
210210

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

471443
#[test]
472-
fn test_wallet_manager_height_operations() {
444+
fn test_wallet_manager_current_height() {
473445
let mut error = FFIError::success();
474446
let error = &mut error as *mut FFIError;
475447

476448
let manager = wallet_manager::wallet_manager_create(FFINetwork::Testnet, error);
477449
assert!(!manager.is_null());
478450

479451
// Get initial height
480-
let _height = unsafe { wallet_manager::wallet_manager_current_height(manager, error) };
452+
let height = unsafe { wallet_manager::wallet_manager_current_height(manager, error) };
453+
assert_eq!(height, 0);
481454

482455
// Update height
483456
let new_height = 12345;
484457
unsafe {
485-
wallet_manager::wallet_manager_update_height(manager, new_height, error);
458+
let manager_ref = &*manager;
459+
manager_ref.runtime.block_on(async {
460+
let mut manager_guard = manager_ref.manager.write().await;
461+
manager_guard.update_height(new_height);
462+
});
486463
}
487464

488465
// 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
@@ -935,9 +935,12 @@ impl<T: WalletInfoInterface> WalletManager<T> {
935935
self.current_height
936936
}
937937

938-
/// Update current block height for a specific network
938+
/// Update current block height and propagate to all wallet infos
939939
pub fn update_height(&mut self, height: u32) {
940-
self.current_height = height
940+
self.current_height = height;
941+
for info in self.wallet_infos.values_mut() {
942+
info.update_synced_height(height);
943+
}
941944
}
942945

943946
/// 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_synced_height(30000);
214+
215+
let wallet_info2 = manager.get_wallet_info_mut(&wallet_id2).unwrap();
216+
wallet_info2.update_synced_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/transaction_checking/wallet_checker.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ mod tests {
827827

828828
// Now advance the chain height past maturity (100 blocks)
829829
let mature_height = block_height + 100;
830-
managed_wallet.update_chain_height(mature_height);
830+
managed_wallet.update_synced_height(mature_height);
831831

832832
// Verify transaction moved from immature to regular
833833
let managed_account =

0 commit comments

Comments
 (0)