2026-02-03 18:12:53 +01:00
# include "logos_execution_zone_wallet_module.h"
2026-02-23 19:28:27 +01:00
# include <algorithm>
2026-06-10 15:16:20 -04:00
# include <cstdio>
# include <cstdlib>
# include <cstring>
# include <vector>
2026-02-18 21:23:16 +01:00
2026-06-10 15:16:20 -04:00
# include <nlohmann/json.hpp>
namespace {
std : : string bytesToHex ( const uint8_t * data , const size_t length ) {
static const char hexChars [ ] = " 0123456789abcdef " ;
std : : string out ;
out . reserve ( length * 2 ) ;
for ( size_t i = 0 ; i < length ; + + i ) {
out . push_back ( hexChars [ ( data [ i ] > > 4 ) & 0xF ] ) ;
out . push_back ( hexChars [ data [ i ] & 0xF ] ) ;
}
return out ;
2026-02-18 21:23:16 +01:00
}
2026-02-23 19:28:27 +01:00
// Balance from wallet_ffi_get_balance is 16 bytes little-endian (u128). Convert to decimal string for UI.
// Requires __uint128_t (GCC/Clang on 64-bit).
2026-06-10 15:16:20 -04:00
std : : string balanceLe16ToDecimalString ( const uint8_t * data ) {
2026-02-23 19:28:27 +01:00
# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ >= 16
__uint128_t v = 0 ;
for ( int i = 0 ; i < 16 ; + + i )
v | = static_cast < __uint128_t > ( data [ i ] ) < < ( i * 8 ) ;
if ( v = = 0 )
2026-06-10 15:16:20 -04:00
return " 0 " ;
2026-02-23 19:28:27 +01:00
char buf [ 40 ] ;
int i = 0 ;
while ( v ) {
buf [ i + + ] = static_cast < char > ( ' 0 ' + ( v % 10 ) ) ;
v / = 10 ;
}
std : : reverse ( buf , buf + i ) ;
2026-06-10 15:16:20 -04:00
return std : : string ( buf , i ) ;
2026-02-23 19:28:27 +01:00
# else
# error "balanceLe16ToDecimalString requires __uint128_t; build with GCC or Clang on 64-bit"
# endif
}
2026-02-18 22:10:38 +01:00
namespace JsonKeys {
2026-06-10 15:16:20 -04:00
constexpr auto TxHash = " tx_hash " ;
constexpr auto Success = " success " ;
constexpr auto Error = " error " ;
constexpr auto ProgramOwner = " program_owner " ;
constexpr auto Balance = " balance " ;
constexpr auto Nonce = " nonce " ;
constexpr auto Data = " data " ;
constexpr auto NullifierPublicKey = " nullifier_public_key " ;
constexpr auto ViewingPublicKey = " viewing_public_key " ;
constexpr auto AccountId = " account_id " ;
constexpr auto IsPublic = " is_public " ;
2026-06-19 13:29:56 +03:00
constexpr auto Secrets = " secrets " ;
2026-02-18 22:52:28 +01:00
} // namespace JsonKeys
2026-02-18 22:10:38 +01:00
2026-06-10 15:16:20 -04:00
bool hexToBytes ( const std : : string & hex , std : : vector < uint8_t > & output_bytes , int expectedLength = - 1 ) {
// Trim whitespace.
size_t start = hex . find_first_not_of ( " \t \n \r \f \v " ) ;
if ( start = = std : : string : : npos ) {
output_bytes . clear ( ) ;
return expectedLength = = - 1 | | expectedLength = = 0 ;
}
size_t end = hex . find_last_not_of ( " \t \n \r \f \v " ) ;
std : : string trimmed = hex . substr ( start , end - start + 1 ) ;
if ( trimmed . size ( ) > = 2 & & trimmed [ 0 ] = = ' 0 ' & & ( trimmed [ 1 ] = = ' x ' | | trimmed [ 1 ] = = ' X ' ) )
trimmed = trimmed . substr ( 2 ) ;
if ( trimmed . size ( ) % 2 ! = 0 )
return false ;
std : : vector < uint8_t > decoded ;
decoded . reserve ( trimmed . size ( ) / 2 ) ;
auto nibble = [ ] ( char c , int & out ) - > bool {
if ( c > = ' 0 ' & & c < = ' 9 ' ) { out = c - ' 0 ' ; return true ; }
if ( c > = ' a ' & & c < = ' f ' ) { out = c - ' a ' + 10 ; return true ; }
if ( c > = ' A ' & & c < = ' F ' ) { out = c - ' A ' + 10 ; return true ; }
2026-02-18 22:52:28 +01:00
return false ;
2026-06-10 15:16:20 -04:00
} ;
for ( size_t i = 0 ; i < trimmed . size ( ) ; i + = 2 ) {
int hi = 0 , lo = 0 ;
if ( ! nibble ( trimmed [ i ] , hi ) | | ! nibble ( trimmed [ i + 1 ] , lo ) )
return false ;
decoded . push_back ( static_cast < uint8_t > ( ( hi < < 4 ) | lo ) ) ;
}
if ( expectedLength ! = - 1 & & static_cast < int > ( decoded . size ( ) ) ! = expectedLength )
2026-02-18 22:52:28 +01:00
return false ;
2026-06-10 15:16:20 -04:00
output_bytes = std : : move ( decoded ) ;
2026-02-18 21:23:16 +01:00
return true ;
}
2026-06-10 15:16:20 -04:00
bool hexToU128 ( const std : : string & hex , uint8_t ( * output ) [ 16 ] ) {
std : : vector < uint8_t > buffer ;
2026-02-18 22:52:28 +01:00
if ( ! hexToBytes ( hex , buffer , 16 ) )
return false ;
2026-06-10 15:16:20 -04:00
memcpy ( output , buffer . data ( ) , 16 ) ;
2026-02-18 21:23:16 +01:00
return true ;
}
2026-06-10 15:16:20 -04:00
std : : string bytes32ToHex ( const FfiBytes32 & bytes ) {
2026-02-18 21:23:16 +01:00
return bytesToHex ( bytes . data , 32 ) ;
}
2026-06-10 15:16:20 -04:00
bool hexToBytes32 ( const std : : string & hex , FfiBytes32 * output_bytes ) {
2026-02-18 22:52:28 +01:00
if ( output_bytes = = nullptr )
return false ;
2026-06-10 15:16:20 -04:00
std : : vector < uint8_t > buffer ;
2026-02-18 22:52:28 +01:00
if ( ! hexToBytes ( hex , buffer , 32 ) )
return false ;
2026-06-10 15:16:20 -04:00
memcpy ( output_bytes - > data , buffer . data ( ) , 32 ) ;
2026-02-18 21:23:16 +01:00
return true ;
}
2026-02-03 18:12:53 +01:00
2026-02-23 19:28:27 +01:00
// Builds JSON { success, tx_hash, error } for both success (result + empty error) and failure (nullptr + errorMessage).
2026-06-10 15:16:20 -04:00
std : : string transferResultToJson ( const FfiTransferResult * result , const std : : string & errorMessage ) {
nlohmann : : json obj = nlohmann : : json : : object ( ) ;
const bool isError = ! errorMessage . empty ( ) ;
obj [ JsonKeys : : Success ] = ! isError & & result & & result - > success ;
obj [ JsonKeys : : TxHash ] = ( ! isError & & result & & result - > tx_hash ) ? std : : string ( result - > tx_hash ) : std : : string ( ) ;
obj [ JsonKeys : : Error ] = errorMessage ;
return obj . dump ( ) ;
}
2026-06-19 13:29:56 +03:00
// Builds JSON { success, tx_hash, secrets, error } for both success (result + empty error) and failure (nullptr + errorMessage) in case of generic transaction.
std : : string genericTransactionResultToJson ( const FfiTransactionResult * result , const std : : string & errorMessage ) {
nlohmann : : json obj = nlohmann : : json : : object ( ) ;
const bool isError = ! errorMessage . empty ( ) ;
obj [ JsonKeys : : Success ] = ! isError & & result & & result - > success ;
obj [ JsonKeys : : TxHash ] = ( ! isError & & result & & result - > tx_hash ) ? std : : string ( result - > tx_hash ) : std : : string ( ) ;
std : : vector < std : : string > secrets ;
if ( ! isError & & result & & result - > secrets_data ) {
for ( uintptr_t i = 0 ; i < result - > secrets_size ; + + i ) {
secrets . push_back ( bytes32ToHex ( result - > secrets_data [ i ] ) ) ;
}
}
obj [ JsonKeys : : Secrets ] = secrets ;
obj [ JsonKeys : : Error ] = errorMessage ;
return obj . dump ( ) ;
}
2026-06-10 15:16:20 -04:00
std : : string ffiAccountToJson ( const FfiAccount & account ) {
nlohmann : : json obj = nlohmann : : json : : object ( ) ;
obj [ JsonKeys : : ProgramOwner ] = bytesToHex ( reinterpret_cast < const uint8_t * > ( account . program_owner . data ) , 32 ) ;
obj [ JsonKeys : : Balance ] = bytesToHex ( account . balance . data , 16 ) ;
obj [ JsonKeys : : Nonce ] = bytesToHex ( account . nonce . data , 16 ) ;
2026-02-18 22:10:38 +01:00
if ( account . data & & account . data_len > 0 ) {
2026-06-10 15:16:20 -04:00
obj [ JsonKeys : : Data ] = bytesToHex ( account . data , account . data_len ) ;
2026-02-18 22:10:38 +01:00
} else {
2026-06-10 15:16:20 -04:00
obj [ JsonKeys : : Data ] = " " ;
2026-02-18 22:10:38 +01:00
}
2026-06-10 15:16:20 -04:00
return obj . dump ( ) ;
2026-02-18 22:10:38 +01:00
}
2026-06-10 15:16:20 -04:00
nlohmann : : json ffiAccountListEntryToJson ( const FfiAccountListEntry & entry ) {
nlohmann : : json obj = nlohmann : : json : : object ( ) ;
obj [ JsonKeys : : AccountId ] = bytes32ToHex ( entry . account_id ) ;
obj [ JsonKeys : : IsPublic ] = entry . is_public ;
return obj ;
2026-02-18 22:10:38 +01:00
}
2026-06-10 15:16:20 -04:00
std : : string ffiPrivateAccountKeysToJson ( const FfiPrivateAccountKeys & keys ) {
nlohmann : : json obj = nlohmann : : json : : object ( ) ;
obj [ JsonKeys : : NullifierPublicKey ] = bytes32ToHex ( keys . nullifier_public_key ) ;
2026-02-18 22:10:38 +01:00
if ( keys . viewing_public_key & & keys . viewing_public_key_len > 0 ) {
2026-06-10 15:16:20 -04:00
obj [ JsonKeys : : ViewingPublicKey ] = bytesToHex ( keys . viewing_public_key , keys . viewing_public_key_len ) ;
2026-02-18 22:10:38 +01:00
} else {
2026-06-10 15:16:20 -04:00
obj [ JsonKeys : : ViewingPublicKey ] = " " ;
2026-02-18 22:10:38 +01:00
}
2026-06-10 15:16:20 -04:00
return obj . dump ( ) ;
2026-02-18 22:10:38 +01:00
}
2026-06-10 15:16:20 -04:00
bool jsonToFfiPrivateAccountKeys ( const std : : string & json , FfiPrivateAccountKeys * output_keys ) {
nlohmann : : json doc = nlohmann : : json : : parse ( json , nullptr , false ) ;
if ( doc . is_discarded ( ) | | ! doc . is_object ( ) )
2026-02-18 22:52:28 +01:00
return false ;
2026-06-10 15:16:20 -04:00
if ( doc . contains ( JsonKeys : : NullifierPublicKey ) & & doc [ JsonKeys : : NullifierPublicKey ] . is_string ( ) ) {
if ( ! hexToBytes32 ( doc [ JsonKeys : : NullifierPublicKey ] . get < std : : string > ( ) , & output_keys - > nullifier_public_key ) )
2026-02-18 22:52:28 +01:00
return false ;
2026-02-18 22:10:38 +01:00
}
2026-06-10 15:16:20 -04:00
if ( doc . contains ( JsonKeys : : ViewingPublicKey ) & & doc [ JsonKeys : : ViewingPublicKey ] . is_string ( ) ) {
std : : vector < uint8_t > buffer ;
if ( ! hexToBytes ( doc [ JsonKeys : : ViewingPublicKey ] . get < std : : string > ( ) , buffer ) )
2026-02-18 22:52:28 +01:00
return false ;
2026-06-10 15:16:20 -04:00
if ( buffer . empty ( ) ) {
output_keys - > viewing_public_key = nullptr ;
output_keys - > viewing_public_key_len = 0 ;
} else {
auto * data = static_cast < uint8_t * > ( malloc ( buffer . size ( ) ) ) ;
memcpy ( data , buffer . data ( ) , buffer . size ( ) ) ;
output_keys - > viewing_public_key = data ;
output_keys - > viewing_public_key_len = buffer . size ( ) ;
}
2026-02-18 22:10:38 +01:00
} else {
2026-02-18 22:18:10 +01:00
output_keys - > viewing_public_key = nullptr ;
output_keys - > viewing_public_key_len = 0 ;
2026-02-18 22:10:38 +01:00
}
2026-02-18 22:52:28 +01:00
2026-02-18 22:10:38 +01:00
return true ;
}
2026-02-20 18:15:25 +01:00
// Parses a JSON array of 32-byte hex strings into a contiguous byte buffer of siblings.
// Returns true on success, with out_len set to the number of siblings and out_bytes sized to out_len*32.
2026-06-10 15:16:20 -04:00
bool jsonArrayHexToSiblings32 ( const std : : string & json_array_str , std : : vector < uint8_t > & out_bytes , uintptr_t & out_len ) {
nlohmann : : json doc = nlohmann : : json : : parse ( json_array_str , nullptr , false ) ;
if ( doc . is_discarded ( ) | | ! doc . is_array ( ) )
2026-02-20 18:15:25 +01:00
return false ;
2026-06-10 15:16:20 -04:00
out_len = static_cast < uintptr_t > ( doc . size ( ) ) ;
2026-02-20 18:15:25 +01:00
out_bytes . clear ( ) ;
2026-06-10 15:16:20 -04:00
out_bytes . reserve ( out_len * 32 ) ;
2026-02-20 18:15:25 +01:00
2026-06-10 15:16:20 -04:00
for ( const auto & v : doc ) {
if ( ! v . is_string ( ) )
2026-02-20 18:15:25 +01:00
return false ;
2026-06-10 15:16:20 -04:00
std : : vector < uint8_t > bytes ;
if ( ! hexToBytes ( v . get < std : : string > ( ) , bytes , 32 ) )
2026-02-20 18:15:25 +01:00
return false ;
2026-06-10 15:16:20 -04:00
out_bytes . insert ( out_bytes . end ( ) , bytes . begin ( ) , bytes . end ( ) ) ;
2026-02-20 18:15:25 +01:00
}
return true ;
}
2026-06-10 15:16:20 -04:00
} // namespace
2026-02-04 16:18:56 +01:00
LogosExecutionZoneWalletModule : : LogosExecutionZoneWalletModule ( ) = default ;
2026-02-18 11:21:00 +00:00
LogosExecutionZoneWalletModule : : ~ LogosExecutionZoneWalletModule ( ) {
if ( walletHandle ) {
wallet_ffi_destroy ( walletHandle ) ;
walletHandle = nullptr ;
}
}
2026-02-03 18:12:53 +01:00
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : name ( ) const {
2026-05-21 17:07:50 +02:00
return " logos_execution_zone " ;
2026-02-03 18:12:53 +01:00
}
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : version ( ) const {
2026-02-03 18:12:53 +01:00
return " 1.0.0 " ;
}
2026-02-04 15:51:02 +01:00
// === Account Management ===
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : create_account_public ( ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
const WalletFfiError error = wallet_ffi_create_account_public ( walletHandle , & id ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " create_account_public: wallet FFI error %d \n " , error ) ;
2026-02-20 08:59:18 +00:00
return { } ;
2026-02-18 21:23:16 +01:00
}
2026-02-20 08:59:18 +00:00
return bytes32ToHex ( id ) ;
2026-02-04 15:51:02 +01:00
}
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : create_account_private ( ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
const WalletFfiError error = wallet_ffi_create_account_private ( walletHandle , & id ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " create_account_private: wallet FFI error %d \n " , error ) ;
2026-02-20 08:59:18 +00:00
return { } ;
2026-02-18 21:23:16 +01:00
}
2026-02-20 08:59:18 +00:00
return bytes32ToHex ( id ) ;
2026-02-04 15:51:02 +01:00
}
2026-06-10 15:16:20 -04:00
LogosList LogosExecutionZoneWalletModule : : list_accounts ( ) {
LogosList result = nlohmann : : json : : array ( ) ;
2026-02-18 22:10:38 +01:00
FfiAccountList list { } ;
const WalletFfiError error = wallet_ffi_list_accounts ( walletHandle , & list ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " list_accounts: wallet FFI error %d \n " , error ) ;
return result ;
2026-02-20 08:59:18 +00:00
}
for ( uintptr_t i = 0 ; i < list . count ; + + i ) {
2026-06-10 15:16:20 -04:00
result . push_back ( ffiAccountListEntryToJson ( list . entries [ i ] ) ) ;
2026-02-18 22:10:38 +01:00
}
2026-02-20 08:59:18 +00:00
wallet_ffi_free_account_list ( & list ) ;
return result ;
2026-02-04 15:51:02 +01:00
}
// === Account Queries ===
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : get_balance ( const std : : string & account_id_hex , const bool is_public ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_id_hex , & id ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " get_balance: invalid account_id_hex \n " ) ;
2026-02-20 08:59:18 +00:00
return { } ;
2026-02-04 15:51:02 +01:00
}
2026-02-18 21:23:16 +01:00
uint8_t balance [ 16 ] = { 0 } ;
const WalletFfiError error = wallet_ffi_get_balance ( walletHandle , & id , is_public , & balance ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " get_balance: wallet FFI error %d \n " , error ) ;
2026-02-20 08:59:18 +00:00
return { } ;
2026-02-18 21:23:16 +01:00
}
2026-02-23 19:28:27 +01:00
// Return decimal string for UI display (balance is 16-byte little-endian u128).
return balanceLe16ToDecimalString ( balance ) ;
}
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : get_account_public ( const std : : string & account_id_hex ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_id_hex , & id ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " get_account_public: invalid account_id_hex \n " ) ;
2026-02-20 08:59:18 +00:00
return { } ;
2026-02-18 21:23:16 +01:00
}
2026-02-18 22:10:38 +01:00
FfiAccount account { } ;
const WalletFfiError error = wallet_ffi_get_account_public ( walletHandle , & id , & account ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " get_account_public: wallet FFI error %d \n " , error ) ;
2026-02-20 08:59:18 +00:00
return { } ;
2026-02-18 22:10:38 +01:00
}
2026-06-10 15:16:20 -04:00
std : : string result = ffiAccountToJson ( account ) ;
2026-02-20 08:59:18 +00:00
wallet_ffi_free_account_data ( & account ) ;
return result ;
2026-02-04 15:51:02 +01:00
}
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : get_account_private ( const std : : string & account_id_hex ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_id_hex , & id ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " get_account_private: invalid account_id_hex \n " ) ;
2026-02-20 08:59:18 +00:00
return { } ;
2026-02-18 21:23:16 +01:00
}
2026-02-18 22:10:38 +01:00
FfiAccount account { } ;
const WalletFfiError error = wallet_ffi_get_account_private ( walletHandle , & id , & account ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " get_account_private: wallet FFI error %d \n " , error ) ;
2026-02-20 08:59:18 +00:00
return { } ;
2026-02-18 22:10:38 +01:00
}
2026-06-10 15:16:20 -04:00
std : : string result = ffiAccountToJson ( account ) ;
2026-02-20 08:59:18 +00:00
wallet_ffi_free_account_data ( & account ) ;
return result ;
2026-02-18 09:20:58 +00:00
}
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : get_public_account_key ( const std : : string & account_id_hex ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_id_hex , & id ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " get_public_account_key: invalid account_id_hex \n " ) ;
2026-02-20 08:59:18 +00:00
return { } ;
2026-02-18 21:23:16 +01:00
}
FfiPublicAccountKey key { } ;
const WalletFfiError error = wallet_ffi_get_public_account_key ( walletHandle , & id , & key ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " get_public_account_key: wallet FFI error %d \n " , error ) ;
2026-02-20 08:59:18 +00:00
return { } ;
2026-02-18 21:23:16 +01:00
}
2026-02-20 08:59:18 +00:00
return bytes32ToHex ( key . public_key ) ;
2026-02-04 15:51:02 +01:00
}
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : get_private_account_keys ( const std : : string & account_id_hex ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_id_hex , & id ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " get_private_account_keys: invalid account_id_hex \n " ) ;
2026-02-20 08:59:18 +00:00
return { } ;
2026-02-18 21:23:16 +01:00
}
2026-02-18 22:10:38 +01:00
FfiPrivateAccountKeys keys { } ;
const WalletFfiError error = wallet_ffi_get_private_account_keys ( walletHandle , & id , & keys ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " get_private_account_keys: wallet FFI error %d \n " , error ) ;
2026-02-20 08:59:18 +00:00
return { } ;
2026-02-18 22:10:38 +01:00
}
2026-06-10 15:16:20 -04:00
std : : string result = ffiPrivateAccountKeysToJson ( keys ) ;
2026-02-20 08:59:18 +00:00
wallet_ffi_free_private_account_keys ( & keys ) ;
return result ;
2026-02-04 15:51:02 +01:00
}
// === Account Encoding ===
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : account_id_to_base58 ( const std : : string & account_id_hex ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_id_hex , & id ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " account_id_to_base58: invalid account_id_hex \n " ) ;
2026-02-18 21:23:16 +01:00
return { } ;
}
char * str = wallet_ffi_account_id_to_base58 ( & id ) ;
2026-02-04 15:51:02 +01:00
if ( ! str ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " account_id_to_base58: wallet_ffi returned null \n " ) ;
2026-02-04 15:51:02 +01:00
return { } ;
}
2026-06-10 15:16:20 -04:00
std : : string value ( str ) ;
2026-02-04 15:51:02 +01:00
wallet_ffi_free_string ( str ) ;
2026-06-10 15:16:20 -04:00
return value ;
2026-02-04 15:51:02 +01:00
}
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : account_id_from_base58 ( const std : : string & base58_str ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
2026-06-10 15:16:20 -04:00
const WalletFfiError error = wallet_ffi_account_id_from_base58 ( base58_str . c_str ( ) , & id ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " account_id_from_base58: wallet FFI error %d \n " , error ) ;
2026-02-20 08:59:18 +00:00
return { } ;
2026-02-18 21:23:16 +01:00
}
2026-02-20 08:59:18 +00:00
return bytes32ToHex ( id ) ;
2026-02-04 15:51:02 +01:00
}
// === Blockchain Synchronisation ===
2026-06-10 15:16:20 -04:00
int64_t LogosExecutionZoneWalletModule : : sync_to_block ( const int64_t block_id ) {
return wallet_ffi_sync_to_block ( walletHandle , static_cast < uint64_t > ( block_id ) ) ;
2026-03-06 00:09:45 +00:00
}
2026-06-10 15:16:20 -04:00
int64_t LogosExecutionZoneWalletModule : : get_last_synced_block ( ) {
2026-02-20 08:59:18 +00:00
uint64_t block_id = 0 ;
const WalletFfiError error = wallet_ffi_get_last_synced_block ( walletHandle , & block_id ) ;
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " get_last_synced_block: wallet FFI error %d \n " , error ) ;
2026-02-20 08:59:18 +00:00
return 0 ;
}
2026-06-10 15:16:20 -04:00
return static_cast < int64_t > ( block_id ) ;
2026-02-04 15:51:02 +01:00
}
2026-06-10 15:16:20 -04:00
int64_t LogosExecutionZoneWalletModule : : get_current_block_height ( ) {
2026-02-20 08:59:18 +00:00
uint64_t block_height = 0 ;
const WalletFfiError error = wallet_ffi_get_current_block_height ( walletHandle , & block_height ) ;
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " get_current_block_height: wallet FFI error %d \n " , error ) ;
2026-02-20 08:59:18 +00:00
return 0 ;
}
2026-06-10 15:16:20 -04:00
return static_cast < int64_t > ( block_height ) ;
2026-02-04 15:51:02 +01:00
}
2026-02-20 18:15:25 +01:00
// === Pinata claiming ===
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : claim_pinata (
const std : : string & pinata_account_id_hex ,
const std : : string & winner_account_id_hex ,
const std : : string & solution_le16_hex
2026-02-20 18:15:25 +01:00
) {
FfiBytes32 pinataId { } , winnerId { } ;
if ( ! hexToBytes32 ( pinata_account_id_hex , & pinataId ) | | ! hexToBytes32 ( winner_account_id_hex , & winnerId ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " claim_pinata: invalid account id hex \n " ) ;
2026-02-20 18:15:25 +01:00
return { } ;
}
uint8_t solution [ 16 ] ;
if ( ! hexToU128 ( solution_le16_hex , & solution ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " claim_pinata: solution_le16_hex must be 32 hex characters (16 bytes) \n " ) ;
2026-02-20 18:15:25 +01:00
return { } ;
}
FfiTransferResult result { } ;
const WalletFfiError error = wallet_ffi_claim_pinata ( walletHandle , & pinataId , & winnerId , & solution , & result ) ;
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " claim_pinata: wallet FFI error %d \n " , error ) ;
2026-02-20 18:15:25 +01:00
return { } ;
}
2026-06-10 15:16:20 -04:00
std : : string resultJson = transferResultToJson ( & result , std : : string ( ) ) ;
2026-02-20 18:15:25 +01:00
wallet_ffi_free_transfer_result ( & result ) ;
return resultJson ;
}
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : claim_pinata_private_owned_already_initialized (
const std : : string & pinata_account_id_hex ,
const std : : string & winner_account_id_hex ,
const std : : string & solution_le16_hex ,
int64_t winner_proof_index ,
const std : : string & winner_proof_siblings_json
2026-02-20 18:15:25 +01:00
) {
FfiBytes32 pinataId { } , winnerId { } ;
if ( ! hexToBytes32 ( pinata_account_id_hex , & pinataId ) | | ! hexToBytes32 ( winner_account_id_hex , & winnerId ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " claim_pinata_private_owned_already_initialized: invalid account id hex \n " ) ;
2026-02-20 18:15:25 +01:00
return { } ;
}
uint8_t solution [ 16 ] ;
if ( ! hexToU128 ( solution_le16_hex , & solution ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " claim_pinata_private_owned_already_initialized: solution_le16_hex must be 32 hex characters (16 bytes) \n " ) ;
2026-02-20 18:15:25 +01:00
return { } ;
}
2026-06-10 15:16:20 -04:00
std : : vector < uint8_t > siblings_bytes ;
2026-02-20 18:15:25 +01:00
uintptr_t siblings_len = 0 ;
if ( ! jsonArrayHexToSiblings32 ( winner_proof_siblings_json , siblings_bytes , siblings_len ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " claim_pinata_private_owned_already_initialized: failed to parse winner_proof_siblings_json \n " ) ;
2026-02-20 18:15:25 +01:00
return { } ;
}
const uint8_t ( * siblings_ptr ) [ 32 ] = nullptr ;
if ( siblings_len > 0 ) {
2026-06-10 15:16:20 -04:00
siblings_ptr = reinterpret_cast < const uint8_t ( * ) [ 32 ] > ( siblings_bytes . data ( ) ) ;
2026-02-20 18:15:25 +01:00
}
FfiTransferResult result { } ;
const WalletFfiError error = wallet_ffi_claim_pinata_private_owned_already_initialized (
walletHandle ,
& pinataId ,
& winnerId ,
& solution ,
static_cast < uintptr_t > ( winner_proof_index ) ,
siblings_ptr ,
siblings_len ,
& result
) ;
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " claim_pinata_private_owned_already_initialized: wallet FFI error %d \n " , error ) ;
2026-02-20 18:15:25 +01:00
return { } ;
}
2026-06-10 15:16:20 -04:00
std : : string resultJson = transferResultToJson ( & result , std : : string ( ) ) ;
2026-02-20 18:15:25 +01:00
wallet_ffi_free_transfer_result ( & result ) ;
return resultJson ;
}
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : claim_pinata_private_owned_not_initialized (
const std : : string & pinata_account_id_hex ,
const std : : string & winner_account_id_hex ,
const std : : string & solution_le16_hex
2026-02-20 18:15:25 +01:00
) {
FfiBytes32 pinataId { } , winnerId { } ;
if ( ! hexToBytes32 ( pinata_account_id_hex , & pinataId ) | | ! hexToBytes32 ( winner_account_id_hex , & winnerId ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " claim_pinata_private_owned_not_initialized: invalid account id hex \n " ) ;
2026-02-20 18:15:25 +01:00
return { } ;
}
uint8_t solution [ 16 ] ;
if ( ! hexToU128 ( solution_le16_hex , & solution ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " claim_pinata_private_owned_not_initialized: solution_le16_hex must be 32 hex characters (16 bytes) \n " ) ;
2026-02-20 18:15:25 +01:00
return { } ;
}
FfiTransferResult result { } ;
const WalletFfiError error = wallet_ffi_claim_pinata_private_owned_not_initialized (
walletHandle ,
& pinataId ,
& winnerId ,
& solution ,
& result
) ;
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " claim_pinata_private_owned_not_initialized: wallet FFI error %d \n " , error ) ;
2026-02-20 18:15:25 +01:00
return { } ;
}
2026-06-10 15:16:20 -04:00
std : : string resultJson = transferResultToJson ( & result , std : : string ( ) ) ;
2026-02-20 18:15:25 +01:00
wallet_ffi_free_transfer_result ( & result ) ;
return resultJson ;
}
2026-02-04 15:51:02 +01:00
// === Operations ===
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : transfer_public (
const std : : string & from_hex ,
const std : : string & to_hex ,
const std : : string & amount_le16_hex
2026-02-04 15:51:02 +01:00
) {
2026-02-18 21:23:16 +01:00
FfiBytes32 fromId { } , toId { } ;
if ( ! hexToBytes32 ( from_hex , & fromId ) | | ! hexToBytes32 ( to_hex , & toId ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_public: invalid account id hex \n " ) ;
return transferResultToJson ( nullptr , " transfer_public: invalid account id hex " ) ;
2026-02-18 21:23:16 +01:00
}
2026-02-18 22:10:38 +01:00
uint8_t amount [ 16 ] ;
if ( ! hexToU128 ( amount_le16_hex , & amount ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_public: amount_le16_hex must be 32 hex characters (16 bytes) \n " ) ;
return transferResultToJson ( nullptr , " transfer_public: amount_le16_hex must be 32 hex characters (16 bytes) " ) ;
2026-02-04 15:51:02 +01:00
}
2026-02-18 22:10:38 +01:00
FfiTransferResult result { } ;
const WalletFfiError error = wallet_ffi_transfer_public ( walletHandle , & fromId , & toId , & amount , & result ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_public: wallet FFI error %d \n " , error ) ;
return transferResultToJson ( nullptr , " transfer_public: wallet FFI error " + std : : to_string ( error ) ) ;
2026-02-18 22:10:38 +01:00
}
2026-06-10 15:16:20 -04:00
std : : string resultJson = transferResultToJson ( & result , std : : string ( ) ) ;
2026-02-20 08:59:18 +00:00
wallet_ffi_free_transfer_result ( & result ) ;
return resultJson ;
2026-02-04 15:51:02 +01:00
}
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : transfer_shielded (
const std : : string & from_hex ,
const std : : string & to_keys_json ,
const std : : string & amount_le16_hex
2026-02-18 09:20:58 +00:00
) {
2026-02-18 21:23:16 +01:00
FfiBytes32 fromId { } ;
if ( ! hexToBytes32 ( from_hex , & fromId ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_shielded: invalid from account id hex \n " ) ;
return transferResultToJson ( nullptr , " transfer_shielded: invalid from account id hex " ) ;
2026-02-18 21:23:16 +01:00
}
2026-02-18 22:10:38 +01:00
FfiPrivateAccountKeys toKeys { } ;
if ( ! jsonToFfiPrivateAccountKeys ( to_keys_json , & toKeys ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_shielded: failed to parse to_keys_json \n " ) ;
return transferResultToJson ( nullptr , " transfer_shielded: failed to parse to_keys_json " ) ;
2026-02-18 09:20:58 +00:00
}
uint8_t amount [ 16 ] ;
2026-02-18 22:10:38 +01:00
if ( ! hexToU128 ( amount_le16_hex , & amount ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_shielded: amount_le16_hex must be 32 hex characters (16 bytes) \n " ) ;
2026-02-18 22:10:38 +01:00
free ( const_cast < uint8_t * > ( toKeys . viewing_public_key ) ) ;
2026-06-10 15:16:20 -04:00
return transferResultToJson ( nullptr , " transfer_shielded: amount_le16_hex must be 32 hex characters (16 bytes) " ) ;
2026-02-18 22:10:38 +01:00
}
2026-02-18 09:20:58 +00:00
2026-06-19 13:29:56 +03:00
// Bandaid, I am not sure, how exactly identifiers should be used.
FfiU128 identifier { } ;
// Keycart not yet supported
const char * key_path = nullptr ;
2026-02-18 22:10:38 +01:00
FfiTransferResult result { } ;
2026-06-19 13:29:56 +03:00
const WalletFfiError error = wallet_ffi_transfer_shielded ( walletHandle , & fromId , & toKeys , & identifier , & amount , key_path , & result ) ;
2026-02-18 22:10:38 +01:00
free ( const_cast < uint8_t * > ( toKeys . viewing_public_key ) ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_shielded: wallet FFI error %d \n " , error ) ;
return transferResultToJson ( nullptr , " transfer_shielded: wallet FFI error " + std : : to_string ( error ) ) ;
2026-02-20 08:59:18 +00:00
}
2026-06-10 15:16:20 -04:00
std : : string resultJson = transferResultToJson ( & result , std : : string ( ) ) ;
2026-02-20 08:59:18 +00:00
wallet_ffi_free_transfer_result ( & result ) ;
return resultJson ;
2026-02-18 09:20:58 +00:00
}
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : transfer_deshielded (
const std : : string & from_hex ,
const std : : string & to_hex ,
const std : : string & amount_le16_hex
2026-02-18 09:20:58 +00:00
) {
2026-02-18 21:23:16 +01:00
FfiBytes32 fromId { } , toId { } ;
if ( ! hexToBytes32 ( from_hex , & fromId ) | | ! hexToBytes32 ( to_hex , & toId ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_deshielded: invalid account id hex \n " ) ;
return transferResultToJson ( nullptr , " transfer_deshielded: invalid account id hex " ) ;
2026-02-18 21:23:16 +01:00
}
2026-02-18 22:10:38 +01:00
uint8_t amount [ 16 ] ;
if ( ! hexToU128 ( amount_le16_hex , & amount ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_deshielded: amount_le16_hex must be 32 hex characters (16 bytes) \n " ) ;
return transferResultToJson ( nullptr , " transfer_deshielded: amount_le16_hex must be 32 hex characters (16 bytes) " ) ;
2026-02-18 09:20:58 +00:00
}
2026-02-18 22:10:38 +01:00
FfiTransferResult result { } ;
const WalletFfiError error = wallet_ffi_transfer_deshielded ( walletHandle , & fromId , & toId , & amount , & result ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_deshielded: wallet FFI error %d \n " , error ) ;
return transferResultToJson ( nullptr , " transfer_deshielded: wallet FFI error " + std : : to_string ( error ) ) ;
2026-02-18 22:10:38 +01:00
}
2026-06-10 15:16:20 -04:00
std : : string resultJson = transferResultToJson ( & result , std : : string ( ) ) ;
2026-02-20 08:59:18 +00:00
wallet_ffi_free_transfer_result ( & result ) ;
return resultJson ;
2026-02-18 09:20:58 +00:00
}
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : transfer_private (
const std : : string & from_hex ,
const std : : string & to_keys_json ,
const std : : string & amount_le16_hex
2026-02-18 09:20:58 +00:00
) {
2026-02-18 21:23:16 +01:00
FfiBytes32 fromId { } ;
if ( ! hexToBytes32 ( from_hex , & fromId ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_private: invalid from account id hex \n " ) ;
return transferResultToJson ( nullptr , " transfer_private: invalid from account id hex " ) ;
2026-02-18 21:23:16 +01:00
}
2026-02-18 22:10:38 +01:00
FfiPrivateAccountKeys toKeys { } ;
if ( ! jsonToFfiPrivateAccountKeys ( to_keys_json , & toKeys ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_private: failed to parse to_keys_json \n " ) ;
return transferResultToJson ( nullptr , " transfer_private: failed to parse to_keys_json " ) ;
2026-02-18 09:20:58 +00:00
}
uint8_t amount [ 16 ] ;
2026-02-18 22:10:38 +01:00
if ( ! hexToU128 ( amount_le16_hex , & amount ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_private: amount_le16_hex must be 32 hex characters (16 bytes) \n " ) ;
2026-02-18 22:10:38 +01:00
free ( const_cast < uint8_t * > ( toKeys . viewing_public_key ) ) ;
2026-06-10 15:16:20 -04:00
return transferResultToJson ( nullptr , " transfer_private: amount_le16_hex must be 32 hex characters (16 bytes) " ) ;
2026-02-18 22:10:38 +01:00
}
2026-02-18 09:20:58 +00:00
2026-06-19 13:29:56 +03:00
// Bandaid, I am not sure, how exactly identifiers should be used.
FfiU128 identifier { } ;
2026-02-18 22:10:38 +01:00
FfiTransferResult result { } ;
2026-06-19 13:29:56 +03:00
const WalletFfiError error = wallet_ffi_transfer_private ( walletHandle , & fromId , & toKeys , & identifier , & amount , & result ) ;
2026-02-18 22:10:38 +01:00
free ( const_cast < uint8_t * > ( toKeys . viewing_public_key ) ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_private: wallet FFI error %d \n " , error ) ;
return transferResultToJson ( nullptr , " transfer_private: wallet FFI error " + std : : to_string ( error ) ) ;
2026-02-20 08:59:18 +00:00
}
2026-06-10 15:16:20 -04:00
std : : string resultJson = transferResultToJson ( & result , std : : string ( ) ) ;
2026-02-20 08:59:18 +00:00
wallet_ffi_free_transfer_result ( & result ) ;
return resultJson ;
2026-02-18 09:20:58 +00:00
}
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : transfer_shielded_owned (
const std : : string & from_hex ,
const std : : string & to_hex ,
const std : : string & amount_le16_hex
2026-02-18 09:20:58 +00:00
) {
2026-02-18 21:23:16 +01:00
FfiBytes32 fromId { } , toId { } ;
if ( ! hexToBytes32 ( from_hex , & fromId ) | | ! hexToBytes32 ( to_hex , & toId ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_shielded_owned: invalid account id hex \n " ) ;
return transferResultToJson ( nullptr , " transfer_shielded_owned: invalid account id hex " ) ;
2026-02-18 21:23:16 +01:00
}
2026-02-18 22:10:38 +01:00
uint8_t amount [ 16 ] ;
if ( ! hexToU128 ( amount_le16_hex , & amount ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_shielded_owned: amount_le16_hex must be 32 hex characters (16 bytes) \n " ) ;
return transferResultToJson ( nullptr , " transfer_shielded_owned: amount_le16_hex must be 32 hex characters (16 bytes) " ) ;
2026-02-18 09:20:58 +00:00
}
2026-06-19 13:29:56 +03:00
// Keycart not yet supported
const char * key_path = nullptr ;
2026-02-18 22:10:38 +01:00
FfiTransferResult result { } ;
2026-06-19 13:29:56 +03:00
const WalletFfiError error = wallet_ffi_transfer_shielded_owned ( walletHandle , & fromId , & toId , & amount , key_path , & result ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_shielded_owned: wallet FFI error %d \n " , error ) ;
return transferResultToJson ( nullptr , " transfer_shielded_owned: wallet FFI error " + std : : to_string ( error ) ) ;
2026-02-18 22:10:38 +01:00
}
2026-06-10 15:16:20 -04:00
std : : string resultJson = transferResultToJson ( & result , std : : string ( ) ) ;
2026-02-20 08:59:18 +00:00
wallet_ffi_free_transfer_result ( & result ) ;
return resultJson ;
2026-02-18 09:20:58 +00:00
}
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : transfer_private_owned (
const std : : string & from_hex ,
const std : : string & to_hex ,
const std : : string & amount_le16_hex
2026-02-18 09:20:58 +00:00
) {
2026-02-18 21:23:16 +01:00
FfiBytes32 fromId { } , toId { } ;
if ( ! hexToBytes32 ( from_hex , & fromId ) | | ! hexToBytes32 ( to_hex , & toId ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_private_owned: invalid account id hex \n " ) ;
return transferResultToJson ( nullptr , " transfer_private_owned: invalid account id hex " ) ;
2026-02-18 21:23:16 +01:00
}
2026-02-18 22:10:38 +01:00
uint8_t amount [ 16 ] ;
if ( ! hexToU128 ( amount_le16_hex , & amount ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_private_owned: amount_le16_hex must be 32 hex characters (16 bytes) \n " ) ;
return transferResultToJson ( nullptr , " transfer_private_owned: amount_le16_hex must be 32 hex characters (16 bytes) " ) ;
2026-02-18 09:20:58 +00:00
}
2026-02-18 22:10:38 +01:00
FfiTransferResult result { } ;
const WalletFfiError error = wallet_ffi_transfer_private_owned ( walletHandle , & fromId , & toId , & amount , & result ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " transfer_private_owned: wallet FFI error %d \n " , error ) ;
return transferResultToJson ( nullptr , " transfer_private_owned: wallet FFI error " + std : : to_string ( error ) ) ;
2026-02-18 22:10:38 +01:00
}
2026-06-10 15:16:20 -04:00
std : : string resultJson = transferResultToJson ( & result , std : : string ( ) ) ;
2026-02-20 08:59:18 +00:00
wallet_ffi_free_transfer_result ( & result ) ;
return resultJson ;
2026-02-18 09:20:58 +00:00
}
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : register_public_account ( const std : : string & account_id_hex ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_id_hex , & id ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " register_public_account: invalid account_id_hex \n " ) ;
return transferResultToJson ( nullptr , " register_public_account: invalid account_id_hex " ) ;
2026-02-18 21:23:16 +01:00
}
2026-02-18 22:10:38 +01:00
FfiTransferResult result { } ;
const WalletFfiError error = wallet_ffi_register_public_account ( walletHandle , & id , & result ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " register_public_account: wallet FFI error %d \n " , error ) ;
return transferResultToJson ( nullptr , " register_public_account: wallet FFI error " + std : : to_string ( error ) ) ;
2026-02-18 22:10:38 +01:00
}
2026-06-10 15:16:20 -04:00
std : : string resultJson = transferResultToJson ( & result , std : : string ( ) ) ;
2026-02-20 08:59:18 +00:00
wallet_ffi_free_transfer_result ( & result ) ;
return resultJson ;
2026-02-04 15:51:02 +01:00
}
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : register_private_account ( const std : : string & account_id_hex ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_id_hex , & id ) ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " register_private_account: invalid account_id_hex \n " ) ;
return transferResultToJson ( nullptr , " register_private_account: invalid account_id_hex " ) ;
2026-02-18 21:23:16 +01:00
}
2026-02-18 22:10:38 +01:00
FfiTransferResult result { } ;
const WalletFfiError error = wallet_ffi_register_private_account ( walletHandle , & id , & result ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " register_private_account: wallet FFI error %d \n " , error ) ;
return transferResultToJson ( nullptr , " register_private_account: wallet FFI error " + std : : to_string ( error ) ) ;
2026-02-18 22:10:38 +01:00
}
2026-06-10 15:16:20 -04:00
std : : string resultJson = transferResultToJson ( & result , std : : string ( ) ) ;
2026-02-20 08:59:18 +00:00
wallet_ffi_free_transfer_result ( & result ) ;
return resultJson ;
2026-02-18 09:20:58 +00:00
}
2026-06-19 13:29:56 +03:00
std : : vector < uint8_t > LogosExecutionZoneWalletModule : : token_elf ( ) {
FfiProgram ffi_program { } ;
WalletFfiError error = wallet_ffi_token_elf ( & ffi_program ) ;
if ( error ! = SUCCESS ) {
fprintf ( stderr , " token_elf: wallet FFI error %d \n " , error ) ;
return std : : vector < uint8_t > { } ;
}
std : : vector < uint8_t > result ( ffi_program . elf_data ,
ffi_program . elf_data + ffi_program . elf_size ) ;
wallet_ffi_free_ffi_program ( & ffi_program ) ;
return result ;
}
std : : vector < uint8_t > LogosExecutionZoneWalletModule : : amm_elf ( ) {
FfiProgram ffi_program { } ;
WalletFfiError error = wallet_ffi_token_elf ( & ffi_program ) ;
if ( error ! = SUCCESS ) {
fprintf ( stderr , " amm_elf: wallet FFI error %d \n " , error ) ;
return std : : vector < uint8_t > { } ;
}
std : : vector < uint8_t > result ( ffi_program . elf_data ,
ffi_program . elf_data + ffi_program . elf_size ) ;
wallet_ffi_free_ffi_program ( & ffi_program ) ;
return result ;
}
std : : vector < uint8_t > LogosExecutionZoneWalletModule : : ata_elf ( ) {
FfiProgram ffi_program { } ;
WalletFfiError error = wallet_ffi_token_elf ( & ffi_program ) ;
if ( error ! = SUCCESS ) {
fprintf ( stderr , " ata_elf: wallet FFI error %d \n " , error ) ;
return std : : vector < uint8_t > { } ;
}
std : : vector < uint8_t > result ( ffi_program . elf_data ,
ffi_program . elf_data + ffi_program . elf_size ) ;
wallet_ffi_free_ffi_program ( & ffi_program ) ;
return result ;
}
std : : vector < uint8_t > LogosExecutionZoneWalletModule : : authenticated_transfer_elf ( ) {
FfiProgram ffi_program { } ;
WalletFfiError error = wallet_ffi_token_elf ( & ffi_program ) ;
if ( error ! = SUCCESS ) {
fprintf ( stderr , " authenticated_transfer_elf: wallet FFI error %d \n " , error ) ;
return std : : vector < uint8_t > { } ;
}
std : : vector < uint8_t > result ( ffi_program . elf_data ,
ffi_program . elf_data + ffi_program . elf_size ) ;
wallet_ffi_free_ffi_program ( & ffi_program ) ;
return result ;
}
std : : string LogosExecutionZoneWalletModule : : send_generic_public_transaction (
const std : : vector < std : : string > & account_ids ,
const std : : vector < bool > & signing_requirements ,
const std : : vector < uint32_t > & instruction ,
const std : : vector < uint8_t > & program_elf ,
const std : : vector < std : : vector < uint8_t > > & program_dependencies
) {
std : : vector < FfiAccountIdentity > identities_resolved ;
identities_resolved . reserve ( account_ids . size ( ) ) ;
for ( int i = 0 ; i < account_ids . size ( ) ; + + i ) {
FfiAccountIdentity acc_identity { } ;
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_ids [ i ] , & id ) ) {
fprintf ( stderr , " wallet_ffi_resolve_public_account: invalid account_id_hex " ) ;
return transferResultToJson ( nullptr , std : : string ( " wallet_ffi_resolve_public_account: invalid account_id_hex " ) ) ;
}
WalletFfiError error = wallet_ffi_resolve_public_account ( id , signing_requirements [ i ] , & acc_identity ) ;
if ( error ! = SUCCESS ) {
fprintf ( stderr , " wallet_ffi_resolve_public_account failed for index %d: wallet FFI error %d \n " , i , error ) ;
return transferResultToJson ( nullptr , std : : string ( " wallet_ffi_resolve_public_account: wallet FFI error " ) + std : : to_string ( error ) ) ;
}
identities_resolved . push_back ( acc_identity ) ;
}
const FfiAccountIdentity * account_identities = identities_resolved . data ( ) ;
uintptr_t account_identities_size = static_cast < uintptr_t > ( identities_resolved . size ( ) ) ;
const uint32_t * input_instruction_data = instruction . data ( ) ;
uintptr_t input_instruction_data_size = static_cast < uintptr_t > ( instruction . size ( ) ) ;
FfiProgram main_program { } ;
const uint8_t * program_elf_data = program_elf . data ( ) ;
uintptr_t program_elf_size = static_cast < uintptr_t > ( program_elf . size ( ) ) ;
main_program . elf_data = program_elf_data ;
main_program . elf_size = program_elf_size ;
std : : vector < FfiProgram > ffi_program_dependencies ;
ffi_program_dependencies . reserve ( program_dependencies . size ( ) ) ;
for ( int i = 0 ; i < program_dependencies . size ( ) ; + + i ) {
FfiProgram program { } ;
const uint8_t * program_elf_data = program_dependencies [ i ] . data ( ) ;
uintptr_t program_elf_size = static_cast < uintptr_t > ( program_dependencies [ i ] . size ( ) ) ;
program . elf_data = program_elf_data ;
program . elf_size = program_elf_size ;
ffi_program_dependencies . push_back ( program ) ;
}
const FfiProgram * dependencies_data = ffi_program_dependencies . data ( ) ;
uintptr_t dependencies_size = static_cast < uintptr_t > ( ffi_program_dependencies . size ( ) ) ;
FfiProgramWithDependencies program_with_dependencies { } ;
program_with_dependencies . program = main_program ;
program_with_dependencies . deps = dependencies_data ;
program_with_dependencies . deps_size = dependencies_size ;
FfiTransactionResult result { } ;
const WalletFfiError error = wallet_ffi_send_generic_public_transaction (
walletHandle ,
account_identities ,
account_identities_size ,
input_instruction_data ,
input_instruction_data_size ,
& program_with_dependencies ,
& result
) ;
for ( FfiAccountIdentity & acc_identity : identities_resolved ) {
wallet_ffi_free_account_identity ( & acc_identity ) ;
}
if ( error ! = SUCCESS ) {
fprintf ( stderr , " send_generic_public_transaction: wallet FFI error %d \n " , error ) ;
return transferResultToJson ( nullptr , std : : string ( " send_generic_public_transaction: wallet FFI error " ) + std : : to_string ( error ) ) ;
}
std : : string resultJson = genericTransactionResultToJson ( & result , std : : string ( ) ) ;
wallet_ffi_free_transaction_result ( & result ) ;
return resultJson ;
}
std : : string LogosExecutionZoneWalletModule : : send_generic_private_transaction (
const std : : vector < std : : string > & account_ids ,
const std : : vector < uint32_t > & instruction ,
const std : : vector < uint8_t > & program_elf ,
const std : : vector < std : : vector < uint8_t > > & program_dependencies
) {
std : : vector < FfiAccountIdentity > identities_resolved ;
identities_resolved . reserve ( account_ids . size ( ) ) ;
for ( int i = 0 ; i < account_ids . size ( ) ; + + i ) {
FfiAccountIdentity acc_identity { } ;
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_ids [ i ] , & id ) ) {
fprintf ( stderr , " wallet_ffi_resolve_private_account: invalid account_id_hex " ) ;
return transferResultToJson ( nullptr , std : : string ( " wallet_ffi_resolve_private_account: invalid account_id_hex " ) ) ;
}
WalletFfiError error = wallet_ffi_resolve_private_account ( walletHandle , id , & acc_identity ) ;
if ( error ! = SUCCESS ) {
fprintf ( stderr , " wallet_ffi_resolve_private_account failed for index %d: wallet FFI error %d \n " , i , error ) ;
return transferResultToJson ( nullptr , std : : string ( " wallet_ffi_resolve_private_account: wallet FFI error " ) + std : : to_string ( error ) ) ;
}
identities_resolved . push_back ( acc_identity ) ;
}
const FfiAccountIdentity * account_identities = identities_resolved . data ( ) ;
uintptr_t account_identities_size = static_cast < uintptr_t > ( identities_resolved . size ( ) ) ;
const uint32_t * input_instruction_data = instruction . data ( ) ;
uintptr_t input_instruction_data_size = static_cast < uintptr_t > ( instruction . size ( ) ) ;
FfiProgram main_program { } ;
const uint8_t * program_elf_data = program_elf . data ( ) ;
uintptr_t program_elf_size = static_cast < uintptr_t > ( program_elf . size ( ) ) ;
main_program . elf_data = program_elf_data ;
main_program . elf_size = program_elf_size ;
std : : vector < FfiProgram > ffi_program_dependencies ;
ffi_program_dependencies . reserve ( program_dependencies . size ( ) ) ;
for ( int i = 0 ; i < program_dependencies . size ( ) ; + + i ) {
FfiProgram program { } ;
const uint8_t * program_elf_data = program_dependencies [ i ] . data ( ) ;
uintptr_t program_elf_size = static_cast < uintptr_t > ( program_dependencies [ i ] . size ( ) ) ;
program . elf_data = program_elf_data ;
program . elf_size = program_elf_size ;
ffi_program_dependencies . push_back ( program ) ;
}
const FfiProgram * dependencies_data = ffi_program_dependencies . data ( ) ;
uintptr_t dependencies_size = static_cast < uintptr_t > ( ffi_program_dependencies . size ( ) ) ;
FfiProgramWithDependencies program_with_dependencies { } ;
program_with_dependencies . program = main_program ;
program_with_dependencies . deps = dependencies_data ;
program_with_dependencies . deps_size = dependencies_size ;
FfiTransactionResult result { } ;
const WalletFfiError error = wallet_ffi_send_generic_private_transaction (
walletHandle ,
account_identities ,
account_identities_size ,
input_instruction_data ,
input_instruction_data_size ,
& program_with_dependencies ,
& result
) ;
for ( FfiAccountIdentity & acc_identity : identities_resolved ) {
wallet_ffi_free_account_identity ( & acc_identity ) ;
}
if ( error ! = SUCCESS ) {
fprintf ( stderr , " send_generic_private_transaction: wallet FFI error %d \n " , error ) ;
return transferResultToJson ( nullptr , std : : string ( " send_generic_private_transaction: wallet FFI error " ) + std : : to_string ( error ) ) ;
}
std : : string resultJson = genericTransactionResultToJson ( & result , std : : string ( ) ) ;
wallet_ffi_free_transaction_result ( & result ) ;
return resultJson ;
}
std : : string LogosExecutionZoneWalletModule : : send_program_deployment_transaction (
const std : : vector < uint8_t > & program_elf
) {
FfiTransactionResult result { } ;
const uint8_t * program_elf_data = program_elf . data ( ) ;
uintptr_t program_elf_size = static_cast < uintptr_t > ( program_elf . size ( ) ) ;
const WalletFfiError error = wallet_ffi_program_deployment (
walletHandle ,
program_elf_data ,
program_elf_size ,
& result
) ;
if ( error ! = SUCCESS ) {
fprintf ( stderr , " send_program_deployment_transaction: wallet FFI error %d \n " , error ) ;
return transferResultToJson ( nullptr , std : : string ( " send_program_deployment_transaction: wallet FFI error " ) + std : : to_string ( error ) ) ;
}
std : : string resultJson = genericTransactionResultToJson ( & result , std : : string ( ) ) ;
wallet_ffi_free_transaction_result ( & result ) ;
return resultJson ;
}
2026-02-04 15:51:02 +01:00
// === Wallet Lifecycle ===
2026-06-22 19:30:57 +03:00
std : : string LogosExecutionZoneWalletModule : : create_new (
2026-06-10 15:16:20 -04:00
const std : : string & config_path ,
const std : : string & storage_path ,
const std : : string & password
2026-02-04 15:51:02 +01:00
) {
2026-02-18 11:21:00 +00:00
if ( walletHandle ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " create_new: wallet is already open \n " ) ;
2026-06-22 19:30:57 +03:00
return { } ;
2026-02-18 11:21:00 +00:00
}
2026-06-22 19:30:57 +03:00
FfiCreateWalletResult create_result = wallet_ffi_create_new ( config_path . c_str ( ) , storage_path . c_str ( ) , password . c_str ( ) ) ;
if ( ! create_result . wallet ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " create_new: wallet_ffi_create_new returned null \n " ) ;
2026-06-22 19:30:57 +03:00
return { } ;
}
walletHandle = create_result . wallet ;
std : : string mnemonic = * create_result . mnemonic ;
return mnemonic ;
}
int64_t LogosExecutionZoneWalletModule : : restore_storage ( const std : : string & mnemonic , const std : : string password ) {
const WalletFfiError error = wallet_ffi_restore_data ( walletHandle , mnemonic . c_str ( ) , password . c_str ( ) ) ;
if ( error ! = SUCCESS ) {
fprintf ( stderr , " restore_storage: wallet FFI error %d \n " , error ) ;
return error ;
2026-02-18 11:21:00 +00:00
}
return SUCCESS ;
2026-02-04 15:51:02 +01:00
}
2026-06-10 15:16:20 -04:00
int64_t LogosExecutionZoneWalletModule : : open ( const std : : string & config_path , const std : : string & storage_path ) {
2026-02-18 11:21:00 +00:00
if ( walletHandle ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " open: wallet is already open \n " ) ;
2026-02-18 11:21:00 +00:00
return INTERNAL_ERROR ;
}
2026-06-10 15:16:20 -04:00
walletHandle = wallet_ffi_open ( config_path . c_str ( ) , storage_path . c_str ( ) ) ;
2026-02-18 11:21:00 +00:00
if ( ! walletHandle ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " open: wallet_ffi_open returned null \n " ) ;
2026-02-18 11:21:00 +00:00
return INTERNAL_ERROR ;
}
return SUCCESS ;
2026-02-04 15:51:02 +01:00
}
2026-06-10 15:16:20 -04:00
int64_t LogosExecutionZoneWalletModule : : save ( ) {
2026-02-18 11:21:00 +00:00
return wallet_ffi_save ( walletHandle ) ;
2026-02-03 18:12:53 +01:00
}
2026-02-04 15:51:02 +01:00
// === Configuration ===
2026-06-10 15:16:20 -04:00
std : : string LogosExecutionZoneWalletModule : : get_sequencer_addr ( ) {
2026-02-18 11:21:00 +00:00
char * addr = wallet_ffi_get_sequencer_addr ( walletHandle ) ;
2026-02-04 15:51:02 +01:00
if ( ! addr ) {
2026-06-10 15:16:20 -04:00
fprintf ( stderr , " get_sequencer_addr: wallet_ffi returned null \n " ) ;
2026-02-04 15:51:02 +01:00
return { } ;
}
2026-06-10 15:16:20 -04:00
std : : string value ( addr ) ;
2026-02-04 15:51:02 +01:00
wallet_ffi_free_string ( addr ) ;
2026-06-10 15:16:20 -04:00
return value ;
2026-06-19 13:29:56 +03:00
}