minor fixes from merging main

ipk -> vpk
IncomingViewingPublicKey -> ViewingPublicKey
This commit is contained in:
jonesmarvin8 2026-02-11 12:11:35 -05:00
parent 6a399ac36c
commit 9e52d41090
8 changed files with 718 additions and 39 deletions

View File

@ -92,7 +92,7 @@ wallet account new private
# Output:
Generated new account with account_id Private/HMRHZdPw4pbyPVZHNGrV6K5AA95wACFsHTRST84fr3CF
With npk 6a2dfe433cf28e525aa0196d719be3c16146f7ee358ca39595323f94fde38f93
With ipk 03d59abf4bee974cc12ddb44641c19f0b5441fef39191f047c988c29a77252a577
With vpk 03d59abf4bee974cc12ddb44641c19f0b5441fef39191f047c988c29a77252a577
```
2. Create the token (Token B):

View File

@ -154,11 +154,11 @@ wallet account new private
# Output:
Generated new account with account_id Private/HacPU3hakLYzWtSqUPw6TUr8fqoMieVWovsUR6sJf7cL
With npk e6366f79d026c8bd64ae6b3d601f0506832ec682ab54897f205fffe64ec0d951
With ipk 02ddc96d0eb56e00ce14994cfdaec5ae1f76244180a919545983156e3519940a17
With vpk 02ddc96d0eb56e00ce14994cfdaec5ae1f76244180a919545983156e3519940a17
```
> [!Tip]
> Focus on the account ID for now. The `npk` and `ipk` values are stored locally and used to build privacy-preserving transactions. The private account ID is derived from `npk`.
> Focus on the account ID for now. The `npk` and `vpk` values are stored locally and used to build privacy-preserving transactions. The private account ID is derived from `npk`.
Just like public accounts, new private accounts start out uninitialized:
@ -228,17 +228,17 @@ wallet account new private
# Output:
Generated new account with account_id Private/AukXPRBmrYVqoqEW2HTs7N3hvTn3qdNFDcxDHVr5hMm5
With npk 0c95ebc4b3830f53da77bb0b80a276a776cdcf6410932acc718dcdb3f788a00e
With ipk 039fd12a3674a880d3e917804129141e4170d419d1f9e28a3dcf979c1f2369cb72
With vpk 039fd12a3674a880d3e917804129141e4170d419d1f9e28a3dcf979c1f2369cb72
```
> [!Tip]
> Ignore the private account ID here and use the `npk` and `ipk` values to send to a foreign private account.
> Ignore the private account ID here and use the `npk` and `vpk` values to send to a foreign private account.
```bash
wallet auth-transfer send \
--from Public/Ev1JprP9BmhbFVQyBcbznU8bAXcwrzwRoPTetXdQPAWS \
--to-npk 0c95ebc4b3830f53da77bb0b80a276a776cdcf6410932acc718dcdb3f788a00e \
--to-ipk 039fd12a3674a880d3e917804129141e4170d419d1f9e28a3dcf979c1f2369cb72 \
--to-vpk 039fd12a3674a880d3e917804129141e4170d419d1f9e28a3dcf979c1f2369cb72 \
--amount 3
```

View File

@ -115,7 +115,7 @@ async fn create_and_transfer_public_token() -> Result<()> {
from: format_public_account_id(&supply_account_id.to_string()),
to: Some(format_public_account_id(&recipient_account_id.to_string())),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: transfer_amount,
};
@ -208,7 +208,7 @@ async fn create_and_transfer_public_token() -> Result<()> {
definition: format_public_account_id(&definition_account_id.to_string()),
holder: Some(format_public_account_id(&recipient_account_id.to_string())),
holder_npk: None,
holder_ipk: None,
holder_vpk: None,
amount: mint_amount,
};
@ -343,7 +343,7 @@ async fn create_and_transfer_token_with_private_supply() -> Result<()> {
from: format_private_account_id(&supply_account_id.to_string()),
to: Some(format_private_account_id(&recipient_account_id.to_string())),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: transfer_amount,
};
@ -527,7 +527,7 @@ async fn create_token_with_private_definition() -> Result<()> {
&recipient_account_id_public.to_string(),
)),
holder_npk: None,
holder_ipk: None,
holder_vpk: None,
amount: mint_amount_public,
};
@ -576,7 +576,7 @@ async fn create_token_with_private_definition() -> Result<()> {
&recipient_account_id_private.to_string(),
)),
holder_npk: None,
holder_ipk: None,
holder_vpk: None,
amount: mint_amount_private,
};
@ -705,7 +705,7 @@ async fn create_token_with_private_definition_and_supply() -> Result<()> {
from: format_private_account_id(&supply_account_id.to_string()),
to: Some(format_private_account_id(&recipient_account_id.to_string())),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: transfer_amount,
};
@ -823,7 +823,7 @@ async fn shielded_token_transfer() -> Result<()> {
from: format_public_account_id(&supply_account_id.to_string()),
to: Some(format_private_account_id(&recipient_account_id.to_string())),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: transfer_amount,
};
@ -937,7 +937,7 @@ async fn deshielded_token_transfer() -> Result<()> {
from: format_private_account_id(&supply_account_id.to_string()),
to: Some(format_public_account_id(&recipient_account_id.to_string())),
to_npk: None,
to_ipk: None,
to_vpk: None,
amount: transfer_amount,
};
@ -1060,7 +1060,7 @@ async fn token_claiming_path_with_private_accounts() -> Result<()> {
definition: format_private_account_id(&definition_account_id.to_string()),
holder: None,
holder_npk: Some(hex::encode(holder_keys.nullifer_public_key.0)),
holder_ipk: Some(hex::encode(holder_keys.incoming_viewing_public_key.0)),
holder_vpk: Some(hex::encode(holder_keys.viewing_public_key.0)),
amount: mint_amount,
};

View File

@ -451,7 +451,7 @@ fn test_wallet_ffi_get_private_account_keys() -> Result<()> {
.0;
let expected_npk = &key_chain.nullifer_public_key;
let expected_ivk = &key_chain.incoming_viewing_public_key;
let expected_ivk = &key_chain.viewing_public_key;
assert_eq!(&keys.npk(), expected_npk);
assert_eq!(&keys.ivk().unwrap(), expected_ivk);

View File

@ -73,7 +73,7 @@ pub unsafe extern "C" fn wallet_ffi_get_public_account_key(
/// Get keys for a private account.
///
/// Returns the nullifier public key (NPK) and incoming viewing public key (IPK)
/// Returns the nullifier public key (NPK) and viewing public key (VPK)
/// for the specified private account. These keys are safe to share publicly.
///
/// # Parameters
@ -130,17 +130,17 @@ pub unsafe extern "C" fn wallet_ffi_get_private_account_keys(
// NPK is a 32-byte array
let npk_bytes = key_chain.nullifer_public_key.0;
// IPK is a compressed secp256k1 point (33 bytes)
let ipk_bytes = key_chain.incoming_viewing_public_key.to_bytes();
let ipk_len = ipk_bytes.len();
let ipk_vec = ipk_bytes.to_vec();
let ipk_boxed = ipk_vec.into_boxed_slice();
let ipk_ptr = Box::into_raw(ipk_boxed) as *const u8;
// VPK is a compressed secp256k1 point (33 bytes)
let vpk_bytes = key_chain.viewing_public_key.to_bytes();
let vpk_len = vpk_bytes.len();
let vpk_vec = vpk_bytes.to_vec();
let vpk_boxed = vpk_vec.into_boxed_slice();
let vpk_ptr = Box::into_raw(vpk_boxed) as *const u8;
unsafe {
(*out_keys).nullifier_public_key.data = npk_bytes;
(*out_keys).incoming_viewing_public_key = ipk_ptr;
(*out_keys).incoming_viewing_public_key_len = ipk_len;
(*out_keys).viewing_public_key = vpk_ptr;
(*out_keys).viewing_public_key_len = vpk_len;
}
WalletFfiError::Success
@ -159,10 +159,10 @@ pub unsafe extern "C" fn wallet_ffi_free_private_account_keys(keys: *mut FfiPriv
unsafe {
let keys = &*keys;
if !keys.incoming_viewing_public_key.is_null() && keys.incoming_viewing_public_key_len > 0 {
if !keys.viewing_public_key.is_null() && keys.viewing_public_key_len > 0 {
let slice = std::slice::from_raw_parts_mut(
keys.incoming_viewing_public_key as *mut u8,
keys.incoming_viewing_public_key_len,
keys.viewing_public_key as *mut u8,
keys.viewing_public_key_len,
);
drop(Box::from_raw(slice as *mut [u8]));
}

View File

@ -72,18 +72,18 @@ impl Default for FfiAccount {
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,
/// viewing public key (compressed secp256k1 point)
pub viewing_public_key: *const u8,
/// Length of viewing public key (typically 33 bytes)
pub 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,
viewing_public_key: std::ptr::null(),
viewing_public_key_len: 0,
}
}
}
@ -156,12 +156,12 @@ impl FfiPrivateAccountKeys {
nssa_core::NullifierPublicKey(self.nullifier_public_key.data)
}
pub fn ivk(&self) -> Result<nssa_core::encryption::IncomingViewingPublicKey, WalletFfiError> {
if self.incoming_viewing_public_key_len == 33 {
pub fn ivk(&self) -> Result<nssa_core::encryption::ViewingPublicKey, WalletFfiError> {
if self.viewing_public_key_len == 33 {
let slice = unsafe {
slice::from_raw_parts(
self.incoming_viewing_public_key,
self.incoming_viewing_public_key_len,
self.viewing_public_key,
self.viewing_public_key_len,
)
};
Ok(Secp256k1Point(slice.to_vec()))

679
wallet-ffi/wallet_ffi.h Normal file
View File

@ -0,0 +1,679 @@
/**
* NSSA Wallet FFI Bindings
*
* Thread Safety: All functions are thread-safe. The wallet handle can be
* shared across threads, but operations are serialized internally.
*
* Memory Management:
* - Functions returning pointers allocate memory that must be freed
* - Use the corresponding wallet_ffi_free_* function to free memory
* - Never free memory returned by FFI using standard C free()
*
* Error Handling:
* - Functions return WalletFfiError codes
* - On error, call wallet_ffi_get_last_error() for detailed message
* - The error string must be freed with wallet_ffi_free_error_string()
*
* Initialization:
* 1. Call wallet_ffi_init_runtime() before any other function
* 2. Create wallet with wallet_ffi_create_new() or wallet_ffi_open()
* 3. Destroy wallet with wallet_ffi_destroy() when done
*/
#ifndef WALLET_FFI_H
#define WALLET_FFI_H
/* Generated with cbindgen:0.29.2 */
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
/**
* Error codes returned by FFI functions.
*/
typedef enum WalletFfiError {
/**
* Operation completed successfully
*/
SUCCESS = 0,
/**
* A null pointer was passed where a valid pointer was expected
*/
NULL_POINTER = 1,
/**
* Invalid UTF-8 string
*/
INVALID_UTF8 = 2,
/**
* Wallet handle is not initialized
*/
WALLET_NOT_INITIALIZED = 3,
/**
* Configuration error
*/
CONFIG_ERROR = 4,
/**
* Storage/persistence error
*/
STORAGE_ERROR = 5,
/**
* Network/RPC error
*/
NETWORK_ERROR = 6,
/**
* Account not found
*/
ACCOUNT_NOT_FOUND = 7,
/**
* Key not found for account
*/
KEY_NOT_FOUND = 8,
/**
* Insufficient funds for operation
*/
INSUFFICIENT_FUNDS = 9,
/**
* Invalid account ID format
*/
INVALID_ACCOUNT_ID = 10,
/**
* Tokio runtime error
*/
RUNTIME_ERROR = 11,
/**
* Password required but not provided
*/
PASSWORD_REQUIRED = 12,
/**
* Block synchronization error
*/
SYNC_ERROR = 13,
/**
* Serialization/deserialization error
*/
SERIALIZATION_ERROR = 14,
/**
* Invalid conversion from FFI types to NSSA types
*/
INVALID_TYPE_CONVERSION = 15,
/**
* Invalid Key value
*/
INVALID_KEY_VALUE = 16,
/**
* Internal error (catch-all)
*/
INTERNAL_ERROR = 99,
} WalletFfiError;
/**
* 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.
*/
typedef struct WalletHandle {
uint8_t _private[0];
} WalletHandle;
/**
* 32-byte array type for AccountId, keys, hashes, etc.
*/
typedef struct FfiBytes32 {
uint8_t data[32];
} FfiBytes32;
/**
* Single entry in the account list.
*/
typedef struct FfiAccountListEntry {
struct FfiBytes32 account_id;
bool is_public;
} FfiAccountListEntry;
/**
* List of accounts returned by wallet_ffi_list_accounts.
*/
typedef struct FfiAccountList {
struct FfiAccountListEntry *entries;
uintptr_t count;
} FfiAccountList;
/**
* Program ID - 8 u32 values (32 bytes total).
*/
typedef struct FfiProgramId {
uint32_t data[8];
} FfiProgramId;
/**
* U128 - 16 bytes little endian
*/
typedef struct FfiU128 {
uint8_t data[16];
} FfiU128;
/**
* Account data structure - C-compatible version of nssa Account.
*
* Note: `balance` and `nonce` are u128 values represented as little-endian
* byte arrays since C doesn't have native u128 support.
*/
typedef struct FfiAccount {
struct FfiProgramId program_owner;
/**
* Balance as little-endian [u8; 16]
*/
struct FfiU128 balance;
/**
* Pointer to account data bytes
*/
const uint8_t *data;
/**
* Length of account data
*/
uintptr_t data_len;
/**
* Nonce as little-endian [u8; 16]
*/
struct FfiU128 nonce;
} FfiAccount;
/**
* Public key info for a public account.
*/
typedef struct FfiPublicAccountKey {
struct FfiBytes32 public_key;
} FfiPublicAccountKey;
/**
* Public keys for a private account (safe to expose).
*/
typedef struct FfiPrivateAccountKeys {
/**
* Nullifier public key (32 bytes)
*/
struct FfiBytes32 nullifier_public_key;
/**
* viewing public key (compressed secp256k1 point)
*/
const uint8_t *viewing_public_key;
/**
* Length of viewing public key (typically 33 bytes)
*/
uintptr_t viewing_public_key_len;
} FfiPrivateAccountKeys;
/**
* Result of a transfer operation.
*/
typedef struct FfiTransferResult {
/**
* Transaction hash (null-terminated string, or null on failure)
*/
char *tx_hash;
/**
* Whether the transfer succeeded
*/
bool success;
} FfiTransferResult;
/**
* Create a new public account.
*
* Public accounts use standard transaction signing and are suitable for
* non-private operations.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `out_account_id`: Output pointer for the new account ID (32 bytes)
*
* # Returns
* - `Success` on successful creation
* - Error code on failure
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `out_account_id` must be a valid pointer to a `FfiBytes32` struct
*/
enum WalletFfiError wallet_ffi_create_account_public(struct WalletHandle *handle,
struct FfiBytes32 *out_account_id);
/**
* Create a new private account.
*
* Private accounts use privacy-preserving transactions with nullifiers
* and commitments.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `out_account_id`: Output pointer for the new account ID (32 bytes)
*
* # Returns
* - `Success` on successful creation
* - Error code on failure
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `out_account_id` must be a valid pointer to a `FfiBytes32` struct
*/
enum WalletFfiError wallet_ffi_create_account_private(struct WalletHandle *handle,
struct FfiBytes32 *out_account_id);
/**
* List all accounts in the wallet.
*
* Returns both public and private accounts managed by this wallet.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `out_list`: Output pointer for the account list
*
* # Returns
* - `Success` on successful listing
* - Error code on failure
*
* # Memory
* The returned list must be freed with `wallet_ffi_free_account_list()`.
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `out_list` must be a valid pointer to a `FfiAccountList` struct
*/
enum WalletFfiError wallet_ffi_list_accounts(struct WalletHandle *handle,
struct FfiAccountList *out_list);
/**
* Free an account list returned by `wallet_ffi_list_accounts`.
*
* # Safety
* The list must be either null or a valid list returned by `wallet_ffi_list_accounts`.
*/
void wallet_ffi_free_account_list(struct FfiAccountList *list);
/**
* Get account balance.
*
* For public accounts, this fetches the balance from the network.
* For private accounts, this returns the locally cached balance.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `account_id`: The account ID (32 bytes)
* - `is_public`: Whether this is a public account
* - `out_balance`: Output for balance as little-endian [u8; 16]
*
* # Returns
* - `Success` on successful query
* - Error code on failure
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `account_id` must be a valid pointer to a `FfiBytes32` struct
* - `out_balance` must be a valid pointer to a `[u8; 16]` array
*/
enum WalletFfiError wallet_ffi_get_balance(struct WalletHandle *handle,
const struct FfiBytes32 *account_id,
bool is_public,
uint8_t (*out_balance)[16]);
/**
* Get full public account data from the network.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `account_id`: The account ID (32 bytes)
* - `out_account`: Output pointer for account data
*
* # Returns
* - `Success` on successful query
* - Error code on failure
*
* # Memory
* The account data must be freed with `wallet_ffi_free_account_data()`.
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `account_id` must be a valid pointer to a `FfiBytes32` struct
* - `out_account` must be a valid pointer to a `FfiAccount` struct
*/
enum WalletFfiError wallet_ffi_get_account_public(struct WalletHandle *handle,
const struct FfiBytes32 *account_id,
struct FfiAccount *out_account);
/**
* Free account data returned by `wallet_ffi_get_account_public`.
*
* # Safety
* The account must be either null or a valid account returned by
* `wallet_ffi_get_account_public`.
*/
void wallet_ffi_free_account_data(struct FfiAccount *account);
/**
* Get the public key for a public account.
*
* This returns the public key derived from the account's signing key.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `account_id`: The account ID (32 bytes)
* - `out_public_key`: Output pointer for the public key
*
* # Returns
* - `Success` on successful retrieval
* - `KeyNotFound` if the account's key is not in this wallet
* - Error code on other failures
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `account_id` must be a valid pointer to a `FfiBytes32` struct
* - `out_public_key` must be a valid pointer to a `FfiPublicAccountKey` struct
*/
enum WalletFfiError wallet_ffi_get_public_account_key(struct WalletHandle *handle,
const struct FfiBytes32 *account_id,
struct FfiPublicAccountKey *out_public_key);
/**
* Get keys for a private account.
*
* Returns the nullifier public key (NPK) and viewing public key (VPK)
* for the specified private account. These keys are safe to share publicly.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `account_id`: The account ID (32 bytes)
* - `out_keys`: Output pointer for the key data
*
* # Returns
* - `Success` on successful retrieval
* - `AccountNotFound` if the private account is not in this wallet
* - Error code on other failures
*
* # Memory
* The keys structure must be freed with `wallet_ffi_free_private_account_keys()`.
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `account_id` must be a valid pointer to a `FfiBytes32` struct
* - `out_keys` must be a valid pointer to a `FfiPrivateAccountKeys` struct
*/
enum WalletFfiError wallet_ffi_get_private_account_keys(struct WalletHandle *handle,
const struct FfiBytes32 *account_id,
struct FfiPrivateAccountKeys *out_keys);
/**
* Free private account keys returned by `wallet_ffi_get_private_account_keys`.
*
* # Safety
* The keys must be either null or valid keys returned by
* `wallet_ffi_get_private_account_keys`.
*/
void wallet_ffi_free_private_account_keys(struct FfiPrivateAccountKeys *keys);
/**
* Convert an account ID to a Base58 string.
*
* # Parameters
* - `account_id`: The account ID (32 bytes)
*
* # Returns
* - Pointer to null-terminated Base58 string on success
* - Null pointer on error
*
* # Memory
* The returned string must be freed with `wallet_ffi_free_string()`.
*
* # Safety
* - `account_id` must be a valid pointer to a `FfiBytes32` struct
*/
char *wallet_ffi_account_id_to_base58(const struct FfiBytes32 *account_id);
/**
* Parse a Base58 string into an account ID.
*
* # Parameters
* - `base58_str`: Null-terminated Base58 string
* - `out_account_id`: Output pointer for the account ID (32 bytes)
*
* # Returns
* - `Success` on successful parsing
* - `InvalidAccountId` if the string is not valid Base58
* - Error code on other failures
*
* # Safety
* - `base58_str` must be a valid pointer to a null-terminated C string
* - `out_account_id` must be a valid pointer to a `FfiBytes32` struct
*/
enum WalletFfiError wallet_ffi_account_id_from_base58(const char *base58_str,
struct FfiBytes32 *out_account_id);
/**
* Synchronize private accounts to a specific block.
*
* This scans the blockchain from the last synced block to the specified block,
* updating private account balances based on any relevant transactions.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `block_id`: Target block number to sync to
*
* # Returns
* - `Success` if synchronization completed
* - `SyncError` if synchronization failed
* - Error code on other failures
*
* # Note
* This operation can take a while for large block ranges. The wallet
* internally uses a progress bar which may output to stdout.
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
*/
enum WalletFfiError wallet_ffi_sync_to_block(struct WalletHandle *handle, uint64_t block_id);
/**
* Get the last synced block number.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `out_block_id`: Output pointer for the block number
*
* # Returns
* - `Success` on success
* - Error code on failure
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `out_block_id` must be a valid pointer to a `u64`
*/
enum WalletFfiError wallet_ffi_get_last_synced_block(struct WalletHandle *handle,
uint64_t *out_block_id);
/**
* Get the current block height from the sequencer.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `out_block_height`: Output pointer for the current block height
*
* # Returns
* - `Success` on success
* - `NetworkError` if the sequencer is unreachable
* - Error code on other failures
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `out_block_height` must be a valid pointer to a `u64`
*/
enum WalletFfiError wallet_ffi_get_current_block_height(struct WalletHandle *handle,
uint64_t *out_block_height);
/**
* Send a public token transfer.
*
* Transfers tokens from one public account to another on the network.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `from`: Source account ID (must be owned by this wallet)
* - `to`: Destination account ID
* - `amount`: Amount to transfer as little-endian [u8; 16]
* - `out_result`: Output pointer for transfer result
*
* # Returns
* - `Success` if the transfer was submitted successfully
* - `InsufficientFunds` if the source account doesn't have enough balance
* - `KeyNotFound` if the source account's signing key is not in this wallet
* - Error code on other failures
*
* # Memory
* The result must be freed with `wallet_ffi_free_transfer_result()`.
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `from` must be a valid pointer to a `FfiBytes32` struct
* - `to` must be a valid pointer to a `FfiBytes32` struct
* - `amount` must be a valid pointer to a `[u8; 16]` array
* - `out_result` must be a valid pointer to a `FfiTransferResult` struct
*/
enum WalletFfiError wallet_ffi_transfer_public(struct WalletHandle *handle,
const struct FfiBytes32 *from,
const struct FfiBytes32 *to,
const uint8_t (*amount)[16],
struct FfiTransferResult *out_result);
/**
* Register a public account on the network.
*
* This initializes a public account on the blockchain. The account must be
* owned by this wallet.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `account_id`: Account ID to register
* - `out_result`: Output pointer for registration result
*
* # Returns
* - `Success` if the registration was submitted successfully
* - Error code on failure
*
* # Memory
* The result must be freed with `wallet_ffi_free_transfer_result()`.
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `account_id` must be a valid pointer to a `FfiBytes32` struct
* - `out_result` must be a valid pointer to a `FfiTransferResult` struct
*/
enum WalletFfiError wallet_ffi_register_public_account(struct WalletHandle *handle,
const struct FfiBytes32 *account_id,
struct FfiTransferResult *out_result);
/**
* Free a transfer result returned by `wallet_ffi_transfer_public` or
* `wallet_ffi_register_public_account`.
*
* # Safety
* The result must be either null or a valid result from a transfer function.
*/
void wallet_ffi_free_transfer_result(struct FfiTransferResult *result);
/**
* Create a new wallet with fresh storage.
*
* This initializes a new wallet with a new seed derived from the password.
* Use this for first-time wallet creation.
*
* # Parameters
* - `config_path`: Path to the wallet configuration file (JSON)
* - `storage_path`: Path where wallet data will be stored
* - `password`: Password for encrypting the wallet seed
*
* # Returns
* - Opaque wallet handle on success
* - Null pointer on error (call `wallet_ffi_get_last_error()` for details)
*
* # Safety
* All string parameters must be valid null-terminated UTF-8 strings.
*/
struct WalletHandle *wallet_ffi_create_new(const char *config_path,
const char *storage_path,
const char *password);
/**
* Open an existing wallet from storage.
*
* This loads a wallet that was previously created with `wallet_ffi_create_new()`.
*
* # Parameters
* - `config_path`: Path to the wallet configuration file (JSON)
* - `storage_path`: Path where wallet data is stored
*
* # Returns
* - Opaque wallet handle on success
* - Null pointer on error (call `wallet_ffi_get_last_error()` for details)
*
* # Safety
* All string parameters must be valid null-terminated UTF-8 strings.
*/
struct WalletHandle *wallet_ffi_open(const char *config_path, const char *storage_path);
/**
* Destroy a wallet handle and free its resources.
*
* After calling this function, the handle is invalid and must not be used.
*
* # Safety
* - The handle must be either null or a valid handle from `wallet_ffi_create_new()` or
* `wallet_ffi_open()`.
* - The handle must not be used after this call.
*/
void wallet_ffi_destroy(struct WalletHandle *handle);
/**
* Save wallet state to persistent storage.
*
* This should be called periodically or after important operations to ensure
* wallet data is persisted to disk.
*
* # Parameters
* - `handle`: Valid wallet handle
*
* # Returns
* - `Success` on successful save
* - Error code on failure
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
*/
enum WalletFfiError wallet_ffi_save(struct WalletHandle *handle);
/**
* Get the sequencer address from the wallet configuration.
*
* # Parameters
* - `handle`: Valid wallet handle
*
* # Returns
* - Pointer to null-terminated string on success (caller must free with
* `wallet_ffi_free_string()`)
* - Null pointer on error
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
*/
char *wallet_ffi_get_sequencer_addr(struct WalletHandle *handle);
/**
* Free a string returned by wallet FFI functions.
*
* # Safety
* The pointer must be either null or a valid string returned by an FFI function.
*/
void wallet_ffi_free_string(char *ptr);
#endif /* WALLET_FFI_H */

View File

@ -1,6 +1,6 @@
use common::{error::ExecutionFailureKind, rpc_primitives::requests::SendTxResponse};
use nssa::{AccountId, program::Program};
use nssa_core::{NullifierPublicKey, SharedSecretKey, encryption::IncomingViewingPublicKey};
use nssa_core::{NullifierPublicKey, SharedSecretKey, encryption::ViewingPublicKey};
use token_core::Instruction;
use crate::{PrivacyPreservingAccount, WalletCore};