From fade3b488ae1d7f6f7f0b3fee8bc6b673a584beb Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Fri, 26 Jun 2026 16:48:00 +0300 Subject: [PATCH] feat(integration_tests): added integration tests for wallet ffi --- integration_tests/tests/wallet_ffi.rs | 152 +++++++++++++++++++++++++- lez/wallet-ffi/src/label.rs | 15 +-- lez/wallet-ffi/src/types.rs | 4 +- 3 files changed, 160 insertions(+), 11 deletions(-) diff --git a/integration_tests/tests/wallet_ffi.rs b/integration_tests/tests/wallet_ffi.rs index 0ef53592..57f1afa4 100644 --- a/integration_tests/tests/wallet_ffi.rs +++ b/integration_tests/tests/wallet_ffi.rs @@ -16,6 +16,7 @@ use std::{ ffi::{CStr, CString, c_char}, io::Write as _, path::Path, + str::FromStr as _, time::Duration, }; @@ -30,9 +31,11 @@ use log::info; use tempfile::tempdir; use wallet::{account::HumanReadableAccount, program_facades::vault::Vault}; use wallet_ffi::{ - FfiAccount, FfiAccountIdentity, FfiAccountList, FfiBytes32, FfiPrivateAccountKeys, - FfiProgramId, FfiPublicAccountKey, FfiTransferResult, FfiU128, WalletHandle, error, + FfiAccount, FfiAccountIdWithPrivacy, FfiAccountIdentity, FfiAccountList, FfiBytes32, + FfiPrivateAccountKeys, FfiProgramId, FfiPublicAccountKey, FfiTransferResult, FfiU128, + WalletHandle, error, generic_transaction::{FfiProgramWithDependencies, FfiTransactionResult}, + label::{AccountIdResolvedFromLabel, LabelAvailability, LabelList}, wallet::FfiCreateWalletOutput, }; @@ -257,6 +260,29 @@ unsafe extern "C" { fn wallet_ffi_free_transaction_result(result: *mut FfiTransactionResult); fn wallet_ffi_free_account_identity(account_identity: *mut FfiAccountIdentity); + + fn wallet_ffi_check_label_available( + handle: *mut WalletHandle, + label: *const c_char, + ) -> LabelAvailability; + + fn wallet_ffi_add_label( + handle: *mut WalletHandle, + label: *const c_char, + account_id_with_privacy: FfiAccountIdWithPrivacy, + ) -> error::WalletFfiError; + + fn wallet_ffi_resolve_label( + handle: *mut WalletHandle, + label: *const c_char, + ) -> AccountIdResolvedFromLabel; + + fn wallet_ffi_get_all_labels_for_account( + handle: *mut WalletHandle, + account_id_with_privacy: FfiAccountIdWithPrivacy, + ) -> LabelList; + + fn wallet_ffi_free_label_list(label_list: *mut LabelList) -> error::WalletFfiError; } fn new_wallet_ffi_with_test_context_config( @@ -1926,3 +1952,125 @@ fn test_wallet_ffi_vault_balance_and_claim_private() -> Result<()> { Ok(()) } + +#[test] +fn test_wallet_ffi_single_label() -> Result<()> { + let ctx = BlockingTestContext::new()?; + let home = tempfile::tempdir()?; + let FfiCreateWalletOutput { + wallet: wallet_ffi_handle, + mnemonic: _, + } = new_wallet_ffi_with_test_context_config(&ctx, home.path())?; + + let mut out_account_id_1 = FfiBytes32::from_bytes([0; 32]); + unsafe { + wallet_ffi_create_account_public(wallet_ffi_handle, &raw mut out_account_id_1).unwrap(); + } + + info!("Waiting for next block creation"); + std::thread::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)); + + let lab_1 = CString::from_str("LABEL1").unwrap().into_raw(); + + let lab_1_availability = unsafe { wallet_ffi_check_label_available(wallet_ffi_handle, lab_1) }; + + assert_eq!(lab_1_availability.error, error::WalletFfiError::Success); + assert!(lab_1_availability.is_available); + + let acc_1_id_with_privacy = FfiAccountIdWithPrivacy { + account_id: out_account_id_1, + is_private: false, + }; + + let err = unsafe { wallet_ffi_add_label(wallet_ffi_handle, lab_1, acc_1_id_with_privacy) }; + + assert_eq!(err, error::WalletFfiError::Success); + + let lab_1_availability = unsafe { wallet_ffi_check_label_available(wallet_ffi_handle, lab_1) }; + + assert!(!lab_1_availability.is_available); + + let acc_resolved = unsafe { wallet_ffi_resolve_label(wallet_ffi_handle, lab_1) }; + + assert_eq!(acc_resolved.account_id, acc_1_id_with_privacy); + + unsafe { + wallet_ffi_free_string(lab_1); + wallet_ffi_destroy(wallet_ffi_handle); + } + + Ok(()) +} + +#[test] +fn test_wallet_ffi_more_labels() -> Result<()> { + let ctx = BlockingTestContext::new()?; + let home = tempfile::tempdir()?; + let FfiCreateWalletOutput { + wallet: wallet_ffi_handle, + mnemonic: _, + } = new_wallet_ffi_with_test_context_config(&ctx, home.path())?; + + let mut out_account_id_1 = FfiBytes32::from_bytes([0; 32]); + unsafe { + wallet_ffi_create_account_public(wallet_ffi_handle, &raw mut out_account_id_1).unwrap(); + } + + info!("Waiting for next block creation"); + std::thread::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)); + + let lab_1 = CString::from_str("LABEL1").unwrap().into_raw(); + let lab_2 = CString::from_str("LABEL2").unwrap().into_raw(); + let lab_3 = CString::from_str("LABEL3").unwrap().into_raw(); + + let acc_1_id_with_privacy = FfiAccountIdWithPrivacy { + account_id: out_account_id_1, + is_private: false, + }; + + let err = unsafe { wallet_ffi_add_label(wallet_ffi_handle, lab_1, acc_1_id_with_privacy) }; + + assert_eq!(err, error::WalletFfiError::Success); + + let err = unsafe { wallet_ffi_add_label(wallet_ffi_handle, lab_2, acc_1_id_with_privacy) }; + + assert_eq!(err, error::WalletFfiError::Success); + + let err = unsafe { wallet_ffi_add_label(wallet_ffi_handle, lab_3, acc_1_id_with_privacy) }; + + assert_eq!(err, error::WalletFfiError::Success); + + let mut label_list_for_out_acc = + unsafe { wallet_ffi_get_all_labels_for_account(wallet_ffi_handle, acc_1_id_with_privacy) }; + + assert_eq!(label_list_for_out_acc.error, error::WalletFfiError::Success); + assert_eq!(label_list_for_out_acc.labels_size, 3); + + let lab_ref_1 = unsafe { &*label_list_for_out_acc.labels_data.add(0) }; + let lab_ref_c_str_1 = unsafe { CStr::from_ptr(*lab_ref_1) }; + + assert_eq!(lab_ref_c_str_1.to_str().unwrap(), "LABEL1"); + + let lab_ref_2 = unsafe { &*label_list_for_out_acc.labels_data.add(1) }; + let lab_ref_c_str_2 = unsafe { CStr::from_ptr(*lab_ref_2) }; + + assert_eq!(lab_ref_c_str_2.to_str().unwrap(), "LABEL2"); + + let lab_ref_3 = unsafe { &*label_list_for_out_acc.labels_data.add(2) }; + let lab_ref_c_str_3 = unsafe { CStr::from_ptr(*lab_ref_3) }; + + assert_eq!(lab_ref_c_str_3.to_str().unwrap(), "LABEL3"); + + let err = unsafe { wallet_ffi_free_label_list(&raw mut label_list_for_out_acc) }; + + assert_eq!(err, error::WalletFfiError::Success); + + unsafe { + wallet_ffi_free_string(lab_1); + wallet_ffi_free_string(lab_2); + wallet_ffi_free_string(lab_3); + wallet_ffi_destroy(wallet_ffi_handle); + } + + Ok(()) +} diff --git a/lez/wallet-ffi/src/label.rs b/lez/wallet-ffi/src/label.rs index 7a3025cd..3f109409 100644 --- a/lez/wallet-ffi/src/label.rs +++ b/lez/wallet-ffi/src/label.rs @@ -12,8 +12,8 @@ use crate::{ #[repr(C)] pub struct LabelAvailability { - is_available: bool, - error: WalletFfiError, + pub is_available: bool, + pub error: WalletFfiError, } impl LabelAvailability { @@ -35,9 +35,10 @@ impl LabelAvailability { } #[repr(C)] +#[derive(Debug, Clone, Copy)] pub struct AccountIdResolvedFromLabel { - account_id: FfiAccountIdWithPrivacy, - error: WalletFfiError, + pub account_id: FfiAccountIdWithPrivacy, + pub error: WalletFfiError, } impl AccountIdResolvedFromLabel { @@ -60,9 +61,9 @@ impl AccountIdResolvedFromLabel { #[repr(C)] pub struct LabelList { - labels_data: *mut *const c_char, - labels_size: usize, - error: WalletFfiError, + pub labels_data: *mut *const c_char, + pub labels_size: usize, + pub error: WalletFfiError, } impl LabelList { diff --git a/lez/wallet-ffi/src/types.rs b/lez/wallet-ffi/src/types.rs index 9930334f..98590619 100644 --- a/lez/wallet-ffi/src/types.rs +++ b/lez/wallet-ffi/src/types.rs @@ -24,7 +24,7 @@ pub struct WalletHandle { /// 32-byte array type for `AccountId`, keys, hashes, etc. #[repr(C)] -#[derive(Clone, Copy, Default)] +#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)] pub struct FfiBytes32 { pub data: [u8; 32], } @@ -594,7 +594,7 @@ impl From for ProgramId { } #[repr(C)] -#[derive(Default)] +#[derive(Default, PartialEq, Eq, Debug, Clone, Copy)] pub struct FfiAccountIdWithPrivacy { pub account_id: FfiBytes32, pub is_private: bool,