Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions key-wallet-ffi/FFI_API.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Functions: 3

### Wallet Manager

Functions: 19
Functions: 18

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

### Wallet Operations

Functions: 62
Functions: 63

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

---

#### `wallet_manager_update_height`

```c
wallet_manager_update_height(manager: *mut FFIWalletManager, height: c_uint, error: *mut FFIError,) -> bool
```

**Description:**
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

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

**Module:** `wallet_manager`

---

#### `wallet_manager_wallet_count`

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

---

#### `managed_wallet_synced_height`

```c
managed_wallet_synced_height(managed_wallet: *const FFIManagedWalletInfo, error: *mut FFIError,) -> c_uint
```

**Description:**
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

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

**Module:** `managed_wallet`

---

#### `wallet_add_account`

```c
Expand Down
29 changes: 14 additions & 15 deletions key-wallet-ffi/include/key_wallet_ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -3089,6 +3089,20 @@ bool managed_wallet_get_balance(const FFIManagedWalletInfo *managed_wallet,
FFIError *error)
;

/*
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
*/

unsigned int managed_wallet_synced_height(const FFIManagedWalletInfo *managed_wallet,
FFIError *error)
;

/*
Free managed wallet info

Expand Down Expand Up @@ -4087,21 +4101,6 @@ bool wallet_manager_process_transaction(FFIWalletManager *manager,
FFIError *error)
;

/*
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
*/

bool wallet_manager_update_height(FFIWalletManager *manager,
unsigned int height,
FFIError *error)
;

/*
Get current height for a network

Expand Down
28 changes: 27 additions & 1 deletion key-wallet-ffi/src/managed_wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
//!

use std::ffi::CString;
use std::os::raw::c_char;
use std::os::raw::{c_char, c_uint};
use std::ptr;

use crate::error::{FFIError, FFIErrorCode};
use crate::types::FFIWallet;
use key_wallet::managed_account::address_pool::KeySource;
use key_wallet::wallet::managed_wallet_info::wallet_info_interface::WalletInfoInterface;
use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo;
use std::ffi::c_void;

Expand Down Expand Up @@ -585,6 +586,31 @@ pub unsafe extern "C" fn managed_wallet_get_balance(
true
}

/// 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
#[no_mangle]
pub unsafe extern "C" fn managed_wallet_synced_height(
managed_wallet: *const FFIManagedWalletInfo,
error: *mut FFIError,
) -> c_uint {
if managed_wallet.is_null() {
FFIError::set_error(
error,
FFIErrorCode::InvalidInput,
"Managed wallet is null".to_string(),
);
return 0;
}
let managed_wallet = unsafe { &*managed_wallet };
FFIError::set_success(error);
managed_wallet.inner().synced_height()
}

/// Free managed wallet info
///
/// # Safety
Expand Down
29 changes: 0 additions & 29 deletions key-wallet-ffi/src/wallet_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -775,35 +775,6 @@ pub unsafe extern "C" fn wallet_manager_process_transaction(
!relevant_wallets.is_empty()
}

/// 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
#[no_mangle]
pub unsafe extern "C" fn wallet_manager_update_height(
manager: *mut FFIWalletManager,
height: c_uint,
error: *mut FFIError,
) -> bool {
if manager.is_null() {
FFIError::set_error(error, FFIErrorCode::InvalidInput, "Manager is null".to_string());
return false;
}

let manager_ref = &*manager;

manager_ref.runtime.block_on(async {
let mut manager_guard = manager_ref.manager.write().await;
manager_guard.update_height(height);
});

FFIError::set_success(error);
true
}

/// Get current height for a network
///
/// # Safety
Expand Down
38 changes: 8 additions & 30 deletions key-wallet-ffi/src/wallet_manager_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,33 +207,6 @@ mod tests {
}
}

#[test]
fn test_height_management() {
let mut error = FFIError::success();
let error = &mut error as *mut FFIError;

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

// Get initial height
let height = unsafe { wallet_manager::wallet_manager_current_height(manager, error) };
assert_eq!(height, 0);

// Update height
let success =
unsafe { wallet_manager::wallet_manager_update_height(manager, 100000, error) };
assert!(success);

// Verify height was updated
let height = unsafe { wallet_manager::wallet_manager_current_height(manager, error) };
assert_eq!(height, 100000);

// Clean up
unsafe {
wallet_manager::wallet_manager_free(manager);
}
}

#[test]
fn test_error_handling() {
let mut error = FFIError::success();
Expand Down Expand Up @@ -465,20 +438,25 @@ mod tests {
}

#[test]
fn test_wallet_manager_height_operations() {
fn test_wallet_manager_current_height() {
let mut error = FFIError::success();
let error = &mut error as *mut FFIError;

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

// Get initial height
let _height = unsafe { wallet_manager::wallet_manager_current_height(manager, error) };
let height = unsafe { wallet_manager::wallet_manager_current_height(manager, error) };
assert_eq!(height, 0);

// Update height
let new_height = 12345;
unsafe {
wallet_manager::wallet_manager_update_height(manager, new_height, error);
let manager_ref = &*manager;
manager_ref.runtime.block_on(async {
let mut manager_guard = manager_ref.manager.write().await;
manager_guard.update_height(new_height);
});
}

// Get updated height
Expand Down
7 changes: 5 additions & 2 deletions key-wallet-manager/src/wallet_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -930,9 +930,12 @@ impl<T: WalletInfoInterface> WalletManager<T> {
self.current_height
}

/// Update current block height for a specific network
/// Update current block height and propagate to all wallet infos
pub fn update_height(&mut self, height: u32) {
self.current_height = height
self.current_height = height;
for info in self.wallet_infos.values_mut() {
info.update_synced_height(height);
}
}

/// Get monitored addresses for all wallets for a specific network
Expand Down
2 changes: 1 addition & 1 deletion key-wallet-manager/src/wallet_manager/process_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl<T: WalletInfoInterface + Send + Sync + 'static> WalletInterface for WalletM
}
}

self.current_height = height;
self.update_height(height);

relevant_txids
}
Expand Down
68 changes: 68 additions & 0 deletions key-wallet-manager/tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use key_wallet::wallet::initialization::WalletAccountCreationOptions;
use key_wallet::wallet::managed_wallet_info::transaction_building::AccountTypePreference;
use key_wallet::wallet::managed_wallet_info::wallet_info_interface::WalletInfoInterface;
use key_wallet::wallet::managed_wallet_info::ManagedWalletInfo;
use key_wallet::{mnemonic::Language, Mnemonic, Network};
use key_wallet_manager::wallet_manager::{WalletError, WalletManager};
Expand Down Expand Up @@ -155,8 +156,75 @@ fn test_balance_calculation() {
fn test_block_height_tracking() {
let mut manager = WalletManager::<ManagedWalletInfo>::new(Network::Testnet);

// Initial state
assert_eq!(manager.current_height(), 0);

// Set height before adding wallets
manager.update_height(1000);
assert_eq!(manager.current_height(), 1000);

let mnemonic1 = Mnemonic::generate(12, Language::English).unwrap();
let wallet_id1 = manager
.create_wallet_from_mnemonic(
&mnemonic1.to_string(),
"",
0,
WalletAccountCreationOptions::Default,
)
.unwrap();

let mnemonic2 = Mnemonic::generate(12, Language::English).unwrap();
let wallet_id2 = manager
.create_wallet_from_mnemonic(
&mnemonic2.to_string(),
"",
0,
WalletAccountCreationOptions::Default,
)
.unwrap();

assert_eq!(manager.wallet_count(), 2);

// Verify both wallets have synced_height of 0 initially
for wallet_info in manager.get_all_wallet_infos().values() {
assert_eq!(wallet_info.synced_height(), 0);
}

// Update height - should propagate to all wallets
manager.update_height(12345);
assert_eq!(manager.current_height(), 12345);

// Verify all wallets got updated
let wallet_info1 = manager.get_wallet_info(&wallet_id1).unwrap();
let wallet_info2 = manager.get_wallet_info(&wallet_id2).unwrap();
assert_eq!(wallet_info1.synced_height(), 12345);
assert_eq!(wallet_info2.synced_height(), 12345);

// Update again - verify subsequent updates work
manager.update_height(20000);
assert_eq!(manager.current_height(), 20000);

for wallet_info in manager.get_all_wallet_infos().values() {
assert_eq!(wallet_info.synced_height(), 20000);
}

// Update wallets individually to different heights
let wallet_info1 = manager.get_wallet_info_mut(&wallet_id1).unwrap();
wallet_info1.update_synced_height(30000);

let wallet_info2 = manager.get_wallet_info_mut(&wallet_id2).unwrap();
wallet_info2.update_synced_height(25000);

// Verify each wallet has its own synced_height
let wallet_info1 = manager.get_wallet_info(&wallet_id1).unwrap();
let wallet_info2 = manager.get_wallet_info(&wallet_id2).unwrap();
assert_eq!(wallet_info1.synced_height(), 30000);
assert_eq!(wallet_info2.synced_height(), 25000);

// Manager update_height still syncs all wallets
manager.update_height(40000);
let wallet_info1 = manager.get_wallet_info(&wallet_id1).unwrap();
let wallet_info2 = manager.get_wallet_info(&wallet_id2).unwrap();
assert_eq!(wallet_info1.synced_height(), 40000);
assert_eq!(wallet_info2.synced_height(), 40000);
}
Loading