//! C-compatible type definitions for the FFI layer. use std::ffi::c_char; /// Opaque pointer to the Wallet instance. /// /// This type is never instantiated directly - it's used as an opaque handle /// to hide the internal wallet structure from C code. #[repr(C)] pub struct WalletHandle { _private: [u8; 0], } /// 32-byte array type for AccountId, keys, hashes, etc. #[repr(C)] #[derive(Clone, Copy, Default)] pub struct FfiBytes32 { pub data: [u8; 32], } /// Program ID - 8 u32 values (32 bytes total). #[repr(C)] #[derive(Clone, Copy, Default)] pub struct FfiProgramId { pub data: [u32; 8], } /// Account data structure - C-compatible version of nssa Account. /// /// Note: `balance` and `nonce` are u128 values split into lo/hi u64 parts /// since C doesn't have native u128 support. #[repr(C)] pub struct FfiAccount { pub program_owner: FfiProgramId, /// Lower 64 bits of balance (u128) pub balance_lo: u64, /// Upper 64 bits of balance (u128) pub balance_hi: u64, /// Pointer to account data bytes pub data: *const u8, /// Length of account data pub data_len: usize, /// Lower 64 bits of nonce (u128) pub nonce_lo: u64, /// Upper 64 bits of nonce (u128) pub nonce_hi: u64, } impl Default for FfiAccount { fn default() -> Self { Self { program_owner: FfiProgramId::default(), balance_lo: 0, balance_hi: 0, data: std::ptr::null(), data_len: 0, nonce_lo: 0, nonce_hi: 0, } } } /// Public keys for a private account (safe to expose). #[repr(C)] pub struct FfiPrivateAccountKeys { /// Nullifier public key (32 bytes) pub nullifier_public_key: FfiBytes32, /// Incoming viewing public key (compressed secp256k1 point) pub incoming_viewing_public_key: *const u8, /// Length of incoming viewing public key (typically 33 bytes) pub incoming_viewing_public_key_len: usize, } impl Default for FfiPrivateAccountKeys { fn default() -> Self { Self { nullifier_public_key: FfiBytes32::default(), incoming_viewing_public_key: std::ptr::null(), incoming_viewing_public_key_len: 0, } } } /// Public key info for a public account. #[repr(C)] #[derive(Clone, Copy, Default)] pub struct FfiPublicAccountKey { pub public_key: FfiBytes32, } /// Single entry in the account list. #[repr(C)] #[derive(Clone, Copy)] pub struct FfiAccountListEntry { pub account_id: FfiBytes32, pub is_public: bool, } /// List of accounts returned by wallet_ffi_list_accounts. #[repr(C)] pub struct FfiAccountList { pub entries: *mut FfiAccountListEntry, pub count: usize, } impl Default for FfiAccountList { fn default() -> Self { Self { entries: std::ptr::null_mut(), count: 0, } } } /// Result of a transfer operation. #[repr(C)] pub struct FfiTransferResult { /// Transaction hash (null-terminated string, or null on failure) pub tx_hash: *mut c_char, /// Whether the transfer succeeded pub success: bool, } impl Default for FfiTransferResult { fn default() -> Self { Self { tx_hash: std::ptr::null_mut(), success: false, } } } // Helper functions to convert between Rust and FFI types impl FfiBytes32 { /// Create from a 32-byte array. pub fn from_bytes(bytes: [u8; 32]) -> Self { Self { data: bytes } } /// Create from an AccountId. pub fn from_account_id(id: &nssa::AccountId) -> Self { Self { data: *id.value() } } } impl From<&nssa::AccountId> for FfiBytes32 { fn from(id: &nssa::AccountId) -> Self { Self::from_account_id(id) } } impl From for nssa::AccountId { fn from(bytes: FfiBytes32) -> Self { nssa::AccountId::new(bytes.data) } } /// Helper to split a u128 into lo/hi u64 parts. pub fn split_u128(value: u128) -> (u64, u64) { (value as u64, (value >> 64) as u64) } /// Helper to combine lo/hi u64 parts into a u128. pub fn combine_u128(lo: u64, hi: u64) -> u128 { (hi as u128) << 64 | (lo as u128) }