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-02-03 18:12:53 +01:00
# include <QtCore/QDebug>
2026-02-18 21:23:16 +01:00
# include <QtCore/QJsonArray>
2026-02-18 22:10:38 +01:00
# include <QtCore/QJsonDocument>
# include <QtCore/QJsonObject>
2026-02-18 21:23:16 +01:00
# include <QtCore/QVariantMap>
static QString bytesToHex ( const uint8_t * data , const size_t length ) {
const QByteArray bytearray ( reinterpret_cast < const char * > ( data ) , static_cast < int > ( length ) ) ;
return QString : : fromLatin1 ( bytearray . toHex ( ) ) ;
}
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).
static QString balanceLe16ToDecimalString ( const uint8_t * data ) {
# 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 )
return QStringLiteral ( " 0 " ) ;
char buf [ 40 ] ;
int i = 0 ;
while ( v ) {
buf [ i + + ] = static_cast < char > ( ' 0 ' + ( v % 10 ) ) ;
v / = 10 ;
}
std : : reverse ( buf , buf + i ) ;
return QString : : fromLatin1 ( buf , i ) ;
# 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-02-18 22:52:28 +01:00
static constexpr auto TxHash = " tx_hash " ;
static constexpr auto Success = " success " ;
2026-02-23 19:28:27 +01:00
static constexpr auto Error = " error " ;
2026-02-18 22:52:28 +01:00
static constexpr auto ProgramOwner = " program_owner " ;
static constexpr auto Balance = " balance " ;
static constexpr auto Nonce = " nonce " ;
static constexpr auto Data = " data " ;
static constexpr auto NullifierPublicKey = " nullifier_public_key " ;
static constexpr auto ViewingPublicKey = " viewing_public_key " ;
static constexpr auto AccountId = " account_id " ;
static constexpr auto IsPublic = " is_public " ;
} // namespace JsonKeys
2026-02-18 22:10:38 +01:00
2026-02-18 21:23:16 +01:00
static bool hexToBytes ( const QString & hex , QByteArray & output_bytes , int expectedLength = - 1 ) {
QString trimmed_hex = hex . trimmed ( ) ;
2026-02-18 22:52:28 +01:00
if ( trimmed_hex . startsWith ( " 0x " , Qt : : CaseInsensitive ) )
trimmed_hex = trimmed_hex . mid ( 2 ) ;
if ( trimmed_hex . size ( ) % 2 ! = 0 )
return false ;
2026-02-18 21:23:16 +01:00
const QByteArray decoded = QByteArray : : fromHex ( trimmed_hex . toLatin1 ( ) ) ;
2026-02-18 22:52:28 +01:00
if ( expectedLength ! = - 1 & & decoded . size ( ) ! = expectedLength )
return false ;
2026-02-18 21:23:16 +01:00
output_bytes = decoded ;
return true ;
}
static bool hexToU128 ( const QString & hex , uint8_t ( * output ) [ 16 ] ) {
QByteArray buffer ;
2026-02-18 22:52:28 +01:00
if ( ! hexToBytes ( hex , buffer , 16 ) )
return false ;
2026-02-18 21:23:16 +01:00
memcpy ( output , buffer . constData ( ) , 16 ) ;
return true ;
}
static QString bytes32ToHex ( const FfiBytes32 & bytes ) {
return bytesToHex ( bytes . data , 32 ) ;
}
static bool hexToBytes32 ( const QString & hex , FfiBytes32 * output_bytes ) {
2026-02-18 22:52:28 +01:00
if ( output_bytes = = nullptr )
return false ;
2026-02-18 21:23:16 +01:00
QByteArray buffer ;
2026-02-18 22:52:28 +01:00
if ( ! hexToBytes ( hex , buffer , 32 ) )
return false ;
2026-02-18 21:23:16 +01:00
memcpy ( output_bytes - > data , buffer . constData ( ) , 32 ) ;
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).
static QString transferResultToJson ( const FfiTransferResult * result , const QString & errorMessage ) {
2026-02-18 22:10:38 +01:00
QVariantMap map ;
2026-02-23 19:28:27 +01:00
const bool isError = ! errorMessage . isEmpty ( ) ;
map [ JsonKeys : : Success ] = ! isError & & result & & result - > success ;
map [ JsonKeys : : TxHash ] = ( ! isError & & result & & result - > tx_hash ) ? QString : : fromUtf8 ( result - > tx_hash ) : QString ( ) ;
map [ JsonKeys : : Error ] = errorMessage ;
2026-02-18 22:10:38 +01:00
return QJsonDocument ( QJsonObject : : fromVariantMap ( map ) ) . toJson ( QJsonDocument : : Compact ) ;
}
2026-06-03 16:38:58 +03:00
// Builds JSON { success, tx_hash, secrets, error } for both success (result + empty error) and failure (nullptr + errorMessage) in case of generic transaction.
static QString genericTransactionResultToJson ( const FfiTransactionResult * result , const QString & errorMessage ) {
QVariantMap map ;
const bool isError = ! errorMessage . isEmpty ( ) ;
map [ JsonKeys : : Success ] = ! isError & & result & & result - > success ;
map [ JsonKeys : : TxHash ] = ( ! isError & & result & & result - > tx_hash ) ? QString : : fromUtf8 ( result - > tx_hash ) : QString ( ) ;
QVariantList secrets ;
if ( ! isError & & result & & result - > secrets_data ) {
for ( uintptr_t i = 0 ; i < result - > secrets_size ; + + i ) {
secrets . append ( bytes32ToHex ( result - > secrets_data [ i ] ) ) ;
}
}
map [ JsonKeys : : Secrets ] = secrets ;
map [ JsonKeys : : Error ] = errorMessage ;
return QJsonDocument ( QJsonObject : : fromVariantMap ( map ) ) . toJson ( QJsonDocument : : Compact ) ;
}
2026-02-18 22:10:38 +01:00
static QString ffiAccountToJson ( const FfiAccount & account ) {
QVariantMap map ;
map [ JsonKeys : : ProgramOwner ] = bytesToHex ( reinterpret_cast < const uint8_t * > ( account . program_owner . data ) , 32 ) ;
map [ JsonKeys : : Balance ] = bytesToHex ( account . balance . data , 16 ) ;
map [ JsonKeys : : Nonce ] = bytesToHex ( account . nonce . data , 16 ) ;
if ( account . data & & account . data_len > 0 ) {
map [ JsonKeys : : Data ] = bytesToHex ( account . data , account . data_len ) ;
} else {
map [ JsonKeys : : Data ] = QString ( ) ;
}
return QJsonDocument ( QJsonObject : : fromVariantMap ( map ) ) . toJson ( QJsonDocument : : Compact ) ;
}
static QJsonObject ffiAccountListEntryToJson ( const FfiAccountListEntry & entry ) {
QVariantMap map ;
map [ JsonKeys : : AccountId ] = bytes32ToHex ( entry . account_id ) ;
map [ JsonKeys : : IsPublic ] = entry . is_public ;
return QJsonObject : : fromVariantMap ( map ) ;
}
static QString ffiPrivateAccountKeysToJson ( const FfiPrivateAccountKeys & keys ) {
QVariantMap map ;
map [ JsonKeys : : NullifierPublicKey ] = bytes32ToHex ( keys . nullifier_public_key ) ;
if ( keys . viewing_public_key & & keys . viewing_public_key_len > 0 ) {
map [ JsonKeys : : ViewingPublicKey ] = bytesToHex ( keys . viewing_public_key , keys . viewing_public_key_len ) ;
} else {
map [ JsonKeys : : ViewingPublicKey ] = QString ( ) ;
}
return QJsonDocument ( QJsonObject : : fromVariantMap ( map ) ) . toJson ( QJsonDocument : : Compact ) ;
}
2026-02-18 22:18:10 +01:00
static bool jsonToFfiPrivateAccountKeys ( const QString & json , FfiPrivateAccountKeys * output_keys ) {
2026-02-18 22:10:38 +01:00
QJsonDocument doc = QJsonDocument : : fromJson ( json . toUtf8 ( ) ) ;
2026-02-18 22:52:28 +01:00
if ( ! doc . isObject ( ) )
return false ;
2026-02-18 22:10:38 +01:00
const QVariantMap map = doc . object ( ) . toVariantMap ( ) ;
2026-02-18 22:52:28 +01:00
2026-02-18 22:10:38 +01:00
if ( map . contains ( JsonKeys : : NullifierPublicKey ) ) {
2026-02-18 22:52:28 +01:00
if ( ! hexToBytes32 ( map [ JsonKeys : : NullifierPublicKey ] . toString ( ) , & output_keys - > nullifier_public_key ) )
return false ;
2026-02-18 22:10:38 +01:00
}
if ( map . contains ( JsonKeys : : ViewingPublicKey ) ) {
QByteArray buffer ;
2026-02-18 22:52:28 +01:00
if ( ! hexToBytes ( map [ JsonKeys : : ViewingPublicKey ] . toString ( ) , buffer ) )
return false ;
2026-02-18 22:10:38 +01:00
uint8_t * data = static_cast < uint8_t * > ( malloc ( buffer . size ( ) ) ) ;
memcpy ( data , buffer . constData ( ) , buffer . size ( ) ) ;
2026-02-18 22:18:10 +01:00
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.
static bool jsonArrayHexToSiblings32 ( const QString & json_array_str , QByteArray & out_bytes , uintptr_t & out_len ) {
QJsonDocument doc = QJsonDocument : : fromJson ( json_array_str . toUtf8 ( ) ) ;
if ( ! doc . isArray ( ) ) {
return false ;
}
const QJsonArray arr = doc . array ( ) ;
out_len = static_cast < uintptr_t > ( arr . size ( ) ) ;
out_bytes . clear ( ) ;
out_bytes . reserve ( static_cast < int > ( out_len * 32 ) ) ;
for ( const QJsonValue & v : arr ) {
if ( ! v . isString ( ) ) {
return false ;
}
QByteArray bytes ;
if ( ! hexToBytes ( v . toString ( ) , bytes , 32 ) ) {
return false ;
}
out_bytes . append ( bytes ) ;
}
return true ;
}
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-02-04 15:51:02 +01:00
// === Plugin Interface ===
2026-02-03 18:12:53 +01:00
QString LogosExecutionZoneWalletModule : : name ( ) const {
2026-05-21 17:07:50 +02:00
return " logos_execution_zone " ;
2026-02-03 18:12:53 +01:00
}
QString LogosExecutionZoneWalletModule : : version ( ) const {
return " 1.0.0 " ;
}
2026-02-04 15:51:02 +01:00
// === Logos Core ===
2026-02-04 16:18:56 +01:00
void LogosExecutionZoneWalletModule : : initLogos ( LogosAPI * logosApiInstance ) {
2026-02-20 11:37:05 +01:00
logosAPI = logosApiInstance ;
2026-02-04 15:51:02 +01:00
}
// === Account Management ===
2026-02-20 08:59:18 +00:00
QString 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 ) {
qWarning ( ) < < " create_account_public: wallet FFI error " < < error ;
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-02-20 08:59:18 +00:00
QString 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 ) {
qWarning ( ) < < " create_account_private: wallet FFI error " < < error ;
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-02-20 08:59:18 +00:00
QJsonArray LogosExecutionZoneWalletModule : : list_accounts ( ) {
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 ) {
qWarning ( ) < < " list_accounts: wallet FFI error " < < error ;
return { } ;
}
QJsonArray result ;
for ( uintptr_t i = 0 ; i < list . count ; + + i ) {
result . append ( 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-02-20 08:59:18 +00:00
QString LogosExecutionZoneWalletModule : : get_balance ( const QString & account_id_hex , const bool is_public ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_id_hex , & id ) ) {
2026-02-20 08:59:18 +00:00
qWarning ( ) < < " get_balance: invalid account_id_hex " ;
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 ) {
qWarning ( ) < < " get_balance: wallet FFI error " < < error ;
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 ) ;
}
QString LogosExecutionZoneWalletModule : : get_balance ( const QString & account_id_hex , const QString & is_public_str ) {
const bool is_public = ( is_public_str = = QStringLiteral ( " true " )
| | is_public_str = = QStringLiteral ( " 1 " )
| | is_public_str . compare ( QStringLiteral ( " yes " ) , Qt : : CaseInsensitive ) = = 0 ) ;
return get_balance ( account_id_hex , is_public ) ;
2026-02-04 15:51:02 +01:00
}
2026-02-20 08:59:18 +00:00
QString LogosExecutionZoneWalletModule : : get_account_public ( const QString & account_id_hex ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_id_hex , & id ) ) {
2026-02-20 08:59:18 +00:00
qWarning ( ) < < " get_account_public: invalid account_id_hex " ;
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 ) {
qWarning ( ) < < " get_account_public: wallet FFI error " < < error ;
return { } ;
2026-02-18 22:10:38 +01:00
}
2026-02-20 08:59:18 +00:00
QString result = ffiAccountToJson ( account ) ;
wallet_ffi_free_account_data ( & account ) ;
return result ;
2026-02-04 15:51:02 +01:00
}
2026-02-20 08:59:18 +00:00
QString LogosExecutionZoneWalletModule : : get_account_private ( const QString & account_id_hex ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_id_hex , & id ) ) {
2026-02-20 08:59:18 +00:00
qWarning ( ) < < " get_account_private: invalid account_id_hex " ;
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 ) {
qWarning ( ) < < " get_account_private: wallet FFI error " < < error ;
return { } ;
2026-02-18 22:10:38 +01:00
}
2026-02-20 08:59:18 +00:00
QString result = ffiAccountToJson ( account ) ;
wallet_ffi_free_account_data ( & account ) ;
return result ;
2026-02-18 09:20:58 +00:00
}
2026-02-20 08:59:18 +00:00
QString LogosExecutionZoneWalletModule : : get_public_account_key ( const QString & account_id_hex ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_id_hex , & id ) ) {
2026-02-20 08:59:18 +00:00
qWarning ( ) < < " get_public_account_key: invalid account_id_hex " ;
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 ) {
qWarning ( ) < < " get_public_account_key: wallet FFI error " < < error ;
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-02-20 08:59:18 +00:00
QString LogosExecutionZoneWalletModule : : get_private_account_keys ( const QString & account_id_hex ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_id_hex , & id ) ) {
2026-02-20 08:59:18 +00:00
qWarning ( ) < < " get_private_account_keys: invalid account_id_hex " ;
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 ) {
qWarning ( ) < < " get_private_account_keys: wallet FFI error " < < error ;
return { } ;
2026-02-18 22:10:38 +01:00
}
2026-02-20 08:59:18 +00:00
QString result = ffiPrivateAccountKeysToJson ( keys ) ;
wallet_ffi_free_private_account_keys ( & keys ) ;
return result ;
2026-02-04 15:51:02 +01:00
}
// === Account Encoding ===
2026-02-18 21:23:16 +01:00
QString LogosExecutionZoneWalletModule : : account_id_to_base58 ( const QString & account_id_hex ) {
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_id_hex , & id ) ) {
return { } ;
}
char * str = wallet_ffi_account_id_to_base58 ( & id ) ;
2026-02-04 15:51:02 +01:00
if ( ! str ) {
return { } ;
}
QString result = QString : : fromUtf8 ( str ) ;
wallet_ffi_free_string ( str ) ;
return result ;
}
2026-02-20 08:59:18 +00:00
QString LogosExecutionZoneWalletModule : : account_id_from_base58 ( const QString & base58_str ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
2026-02-04 16:18:56 +01:00
const QByteArray utf8 = base58_str . toUtf8 ( ) ;
2026-02-18 21:23:16 +01:00
const WalletFfiError error = wallet_ffi_account_id_from_base58 ( utf8 . constData ( ) , & id ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
qWarning ( ) < < " account_id_from_base58: wallet FFI error " < < error ;
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-02-20 17:59:10 +01:00
int LogosExecutionZoneWalletModule : : sync_to_block ( const uint64_t block_id ) {
2026-02-18 11:21:00 +00:00
return wallet_ffi_sync_to_block ( walletHandle , block_id ) ;
2026-02-04 15:51:02 +01:00
}
2026-03-06 00:09:45 +00:00
int LogosExecutionZoneWalletModule : : sync_to_block ( const QString & block_id_str ) {
bool ok = false ;
const uint64_t block_id = block_id_str . trimmed ( ) . toULongLong ( & ok ) ;
if ( ! ok ) {
qWarning ( ) < < " sync_to_block: invalid block id string: " < < block_id_str ;
return - 1 ;
}
return sync_to_block ( block_id ) ;
}
int 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 ) {
qWarning ( ) < < " get_last_synced_block: wallet FFI error " < < error ;
return 0 ;
}
2026-03-06 00:09:45 +00:00
return static_cast < int > ( block_id ) ;
2026-02-04 15:51:02 +01:00
}
2026-03-06 00:09:45 +00:00
int 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 ) {
qWarning ( ) < < " get_current_block_height: wallet FFI error " < < error ;
return 0 ;
}
2026-03-06 00:09:45 +00:00
return static_cast < int > ( block_height ) ;
2026-02-04 15:51:02 +01:00
}
2026-02-20 18:15:25 +01:00
// === Pinata claiming ===
QString LogosExecutionZoneWalletModule : : claim_pinata (
const QString & pinata_account_id_hex ,
const QString & winner_account_id_hex ,
const QString & solution_le16_hex
) {
FfiBytes32 pinataId { } , winnerId { } ;
if ( ! hexToBytes32 ( pinata_account_id_hex , & pinataId ) | | ! hexToBytes32 ( winner_account_id_hex , & winnerId ) ) {
qWarning ( ) < < " claim_pinata: invalid account id hex " ;
return { } ;
}
uint8_t solution [ 16 ] ;
if ( ! hexToU128 ( solution_le16_hex , & solution ) ) {
qWarning ( ) < < " claim_pinata: solution_le16_hex must be 32 hex characters (16 bytes) " ;
return { } ;
}
FfiTransferResult result { } ;
const WalletFfiError error = wallet_ffi_claim_pinata ( walletHandle , & pinataId , & winnerId , & solution , & result ) ;
if ( error ! = SUCCESS ) {
qWarning ( ) < < " claim_pinata: wallet FFI error " < < error ;
return { } ;
}
2026-02-23 19:28:27 +01:00
QString resultJson = transferResultToJson ( & result , QString ( ) ) ;
2026-02-20 18:15:25 +01:00
wallet_ffi_free_transfer_result ( & result ) ;
return resultJson ;
}
QString LogosExecutionZoneWalletModule : : claim_pinata_private_owned_already_initialized (
const QString & pinata_account_id_hex ,
const QString & winner_account_id_hex ,
const QString & solution_le16_hex ,
uint64_t winner_proof_index ,
const QString & winner_proof_siblings_json
) {
FfiBytes32 pinataId { } , winnerId { } ;
if ( ! hexToBytes32 ( pinata_account_id_hex , & pinataId ) | | ! hexToBytes32 ( winner_account_id_hex , & winnerId ) ) {
qWarning ( ) < < " claim_pinata_private_owned_already_initialized: invalid account id hex " ;
return { } ;
}
uint8_t solution [ 16 ] ;
if ( ! hexToU128 ( solution_le16_hex , & solution ) ) {
qWarning ( ) < < " claim_pinata_private_owned_already_initialized: solution_le16_hex must be 32 hex characters (16 bytes) " ;
return { } ;
}
QByteArray siblings_bytes ;
uintptr_t siblings_len = 0 ;
if ( ! jsonArrayHexToSiblings32 ( winner_proof_siblings_json , siblings_bytes , siblings_len ) ) {
qWarning ( ) < < " claim_pinata_private_owned_already_initialized: failed to parse winner_proof_siblings_json " ;
return { } ;
}
const uint8_t ( * siblings_ptr ) [ 32 ] = nullptr ;
if ( siblings_len > 0 ) {
siblings_ptr = reinterpret_cast < const uint8_t ( * ) [ 32 ] > ( siblings_bytes . constData ( ) ) ;
}
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 ) {
qWarning ( ) < < " claim_pinata_private_owned_already_initialized: wallet FFI error " < < error ;
return { } ;
}
2026-02-23 19:28:27 +01:00
QString resultJson = transferResultToJson ( & result , QString ( ) ) ;
2026-02-20 18:15:25 +01:00
wallet_ffi_free_transfer_result ( & result ) ;
return resultJson ;
}
QString LogosExecutionZoneWalletModule : : claim_pinata_private_owned_not_initialized (
const QString & pinata_account_id_hex ,
const QString & winner_account_id_hex ,
const QString & solution_le16_hex
) {
FfiBytes32 pinataId { } , winnerId { } ;
if ( ! hexToBytes32 ( pinata_account_id_hex , & pinataId ) | | ! hexToBytes32 ( winner_account_id_hex , & winnerId ) ) {
qWarning ( ) < < " claim_pinata_private_owned_not_initialized: invalid account id hex " ;
return { } ;
}
uint8_t solution [ 16 ] ;
if ( ! hexToU128 ( solution_le16_hex , & solution ) ) {
qWarning ( ) < < " claim_pinata_private_owned_not_initialized: solution_le16_hex must be 32 hex characters (16 bytes) " ;
return { } ;
}
FfiTransferResult result { } ;
const WalletFfiError error = wallet_ffi_claim_pinata_private_owned_not_initialized (
walletHandle ,
& pinataId ,
& winnerId ,
& solution ,
& result
) ;
if ( error ! = SUCCESS ) {
qWarning ( ) < < " claim_pinata_private_owned_not_initialized: wallet FFI error " < < error ;
return { } ;
}
2026-02-23 19:28:27 +01:00
QString resultJson = transferResultToJson ( & result , QString ( ) ) ;
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-02-20 08:59:18 +00:00
QString LogosExecutionZoneWalletModule : : transfer_public (
2026-02-18 21:23:16 +01:00
const QString & from_hex ,
const QString & to_hex ,
2026-02-20 08:59:18 +00:00
const QString & 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-02-20 08:59:18 +00:00
qWarning ( ) < < " transfer_public: invalid account id hex " ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " 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-02-18 21:23:16 +01:00
qWarning ( ) < < " transfer_public: amount_le16_hex must be 32 hex characters (16 bytes) " ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " 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 ) {
qWarning ( ) < < " transfer_public: wallet FFI error " < < error ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " transfer_public: wallet FFI error " ) + QString : : number ( error ) ) ;
2026-02-18 22:10:38 +01:00
}
2026-02-23 19:28:27 +01:00
QString resultJson = transferResultToJson ( & result , QString ( ) ) ;
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-02-20 08:59:18 +00:00
QString LogosExecutionZoneWalletModule : : transfer_shielded (
2026-02-18 21:23:16 +01:00
const QString & from_hex ,
2026-02-18 22:10:38 +01:00
const QString & to_keys_json ,
2026-02-20 08:59:18 +00:00
const QString & 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-02-20 08:59:18 +00:00
qWarning ( ) < < " transfer_shielded: invalid from account id hex " ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " 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-02-20 08:59:18 +00:00
qWarning ( ) < < " transfer_shielded: failed to parse to_keys_json " ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " 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 ) ) {
qWarning ( ) < < " transfer_shielded: amount_le16_hex must be 32 hex characters (16 bytes) " ;
free ( const_cast < uint8_t * > ( toKeys . viewing_public_key ) ) ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " 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-02-18 22:10:38 +01:00
FfiTransferResult result { } ;
const WalletFfiError error = wallet_ffi_transfer_shielded ( walletHandle , & fromId , & toKeys , & amount , & result ) ;
free ( const_cast < uint8_t * > ( toKeys . viewing_public_key ) ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
qWarning ( ) < < " transfer_shielded: wallet FFI error " < < error ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " transfer_shielded: wallet FFI error " ) + QString : : number ( error ) ) ;
2026-02-20 08:59:18 +00:00
}
2026-02-23 19:28:27 +01:00
QString resultJson = transferResultToJson ( & result , QString ( ) ) ;
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-02-20 08:59:18 +00:00
QString LogosExecutionZoneWalletModule : : transfer_deshielded (
2026-02-18 21:23:16 +01:00
const QString & from_hex ,
const QString & to_hex ,
2026-02-20 08:59:18 +00:00
const QString & 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-02-20 08:59:18 +00:00
qWarning ( ) < < " transfer_deshielded: invalid account id hex " ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " 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-02-18 21:23:16 +01:00
qWarning ( ) < < " transfer_deshielded: amount_le16_hex must be 32 hex characters (16 bytes) " ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " 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 ) {
qWarning ( ) < < " transfer_deshielded: wallet FFI error " < < error ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " transfer_deshielded: wallet FFI error " ) + QString : : number ( error ) ) ;
2026-02-18 22:10:38 +01:00
}
2026-02-23 19:28:27 +01:00
QString resultJson = transferResultToJson ( & result , QString ( ) ) ;
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-02-20 08:59:18 +00:00
QString LogosExecutionZoneWalletModule : : transfer_private (
2026-02-18 21:23:16 +01:00
const QString & from_hex ,
2026-02-18 22:10:38 +01:00
const QString & to_keys_json ,
2026-02-20 08:59:18 +00:00
const QString & 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-02-20 08:59:18 +00:00
qWarning ( ) < < " transfer_private: invalid from account id hex " ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " 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-02-20 08:59:18 +00:00
qWarning ( ) < < " transfer_private: failed to parse to_keys_json " ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " 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 ) ) {
qWarning ( ) < < " transfer_private: amount_le16_hex must be 32 hex characters (16 bytes) " ;
free ( const_cast < uint8_t * > ( toKeys . viewing_public_key ) ) ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " 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-02-18 22:10:38 +01:00
FfiTransferResult result { } ;
const WalletFfiError error = wallet_ffi_transfer_private ( walletHandle , & fromId , & toKeys , & amount , & result ) ;
free ( const_cast < uint8_t * > ( toKeys . viewing_public_key ) ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
qWarning ( ) < < " transfer_private: wallet FFI error " < < error ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " transfer_private: wallet FFI error " ) + QString : : number ( error ) ) ;
2026-02-20 08:59:18 +00:00
}
2026-02-23 19:28:27 +01:00
QString resultJson = transferResultToJson ( & result , QString ( ) ) ;
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-02-20 08:59:18 +00:00
QString LogosExecutionZoneWalletModule : : transfer_shielded_owned (
2026-02-18 21:23:16 +01:00
const QString & from_hex ,
const QString & to_hex ,
2026-02-20 08:59:18 +00:00
const QString & 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-02-20 08:59:18 +00:00
qWarning ( ) < < " transfer_shielded_owned: invalid account id hex " ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " 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-02-18 21:23:16 +01:00
qWarning ( ) < < " transfer_shielded_owned: amount_le16_hex must be 32 hex characters (16 bytes) " ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " transfer_shielded_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_shielded_owned ( walletHandle , & fromId , & toId , & amount , & result ) ;
2026-02-20 08:59:18 +00:00
if ( error ! = SUCCESS ) {
qWarning ( ) < < " transfer_shielded_owned: wallet FFI error " < < error ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " transfer_shielded_owned: wallet FFI error " ) + QString : : number ( error ) ) ;
2026-02-18 22:10:38 +01:00
}
2026-02-23 19:28:27 +01:00
QString resultJson = transferResultToJson ( & result , QString ( ) ) ;
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-02-20 08:59:18 +00:00
QString LogosExecutionZoneWalletModule : : transfer_private_owned (
2026-02-18 21:23:16 +01:00
const QString & from_hex ,
const QString & to_hex ,
2026-02-20 08:59:18 +00:00
const QString & 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-02-20 08:59:18 +00:00
qWarning ( ) < < " transfer_private_owned: invalid account id hex " ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " 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-02-18 21:23:16 +01:00
qWarning ( ) < < " transfer_private_owned: amount_le16_hex must be 32 hex characters (16 bytes) " ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " 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 ) {
qWarning ( ) < < " transfer_private_owned: wallet FFI error " < < error ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " transfer_private_owned: wallet FFI error " ) + QString : : number ( error ) ) ;
2026-02-18 22:10:38 +01:00
}
2026-02-23 19:28:27 +01:00
QString resultJson = transferResultToJson ( & result , QString ( ) ) ;
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-02-20 08:59:18 +00:00
QString LogosExecutionZoneWalletModule : : register_public_account ( const QString & account_id_hex ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_id_hex , & id ) ) {
2026-02-20 08:59:18 +00:00
qWarning ( ) < < " register_public_account: invalid account_id_hex " ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " 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 ) {
qWarning ( ) < < " register_public_account: wallet FFI error " < < error ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " register_public_account: wallet FFI error " ) + QString : : number ( error ) ) ;
2026-02-18 22:10:38 +01:00
}
2026-02-23 19:28:27 +01:00
QString resultJson = transferResultToJson ( & result , QString ( ) ) ;
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-02-20 08:59:18 +00:00
QString LogosExecutionZoneWalletModule : : register_private_account ( const QString & account_id_hex ) {
2026-02-18 21:23:16 +01:00
FfiBytes32 id { } ;
if ( ! hexToBytes32 ( account_id_hex , & id ) ) {
2026-02-20 08:59:18 +00:00
qWarning ( ) < < " register_private_account: invalid account_id_hex " ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " 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 ) {
qWarning ( ) < < " register_private_account: wallet FFI error " < < error ;
2026-02-23 19:28:27 +01:00
return transferResultToJson ( nullptr , QStringLiteral ( " register_private_account: wallet FFI error " ) + QString : : number ( error ) ) ;
2026-02-18 22:10:38 +01:00
}
2026-02-23 19:28:27 +01:00
QString resultJson = transferResultToJson ( & result , QString ( ) ) ;
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-03 16:38:58 +03:00
QList < uint32_t > LogosExecutionZoneWalletModule : : serialization_helper ( const QList < uint8_t > & input_data ) {
const uint8_t * input_instruction_data = input_data . constData ( ) ;
uintptr_t input_instruction_data_size = static_cast < uintptr_t > ( input_data . size ( ) ) ;
FfiInstructionWords raw_words = wallet_ffi_serialization_helper ( input_instruction_data , input_instruction_data_size ) ;
if ( raw_words . error ! = SUCCESS ) {
qWarning ( ) < < " serialization_helper: wallet FFI error " < < raw_words . error ;
return QList < uint32_t > { } ;
}
QList < uint32_t > result ( raw_words . instruction_words , raw_words . instruction_words + raw_words . instruction_words_size ) ;
wallet_ffi_free_instruction_words ( & raw_words ) ;
return result ;
}
QString send_generic_public_transaction (
const QList < FfiBytes32 > & account_ids ,
const QList < bool > & signing_requirements ,
const QList < uint8_t > & instruction ,
const QList < uint8_t > & program_elf ,
const QList < QList < uint8_t > > & program_dependencies ,
) {
QList < FfiAccountIdentity > identities_resolved ;
identities_resolved . reserve ( account_ids . size ( ) ) ;
for ( int i = 0 ; i < account_ids . size ( ) ; + + i ) {
FfiAccountIdentity acc_identity { } ;
WalletFfiError error = wallet_ffi_resolve_public_account ( account_ids [ i ] , signing_requirements [ i ] , & acc_identity ) ;
if ( error ! = SUCCESS ) {
qWarning ( ) < < " wallet_ffi_resolve_public_account failed for index " < < i < < " : wallet FFI error " < < error ;
return transferResultToJson ( nullptr , QStringLiteral ( " wallet_ffi_resolve_public_account: wallet FFI error " ) + QString : : number ( error ) ) ;
}
resolved . append ( acc_identity ) ;
}
const FfiAccountIdentity * account_identities = resolved . constData ( ) ;
uintptr_t account_identities_size = static_cast < uintptr_t > ( resolved . size ( ) ) ;
const uint8_t * input_instruction_data = instruction . constData ( ) ;
uintptr_t input_instruction_data_size = static_cast < uintptr_t > ( instruction . size ( ) ) ;
FfiInstructionWords raw_words = wallet_ffi_serialization_helper ( input_instruction_data , input_instruction_data_size ) ;
if ( raw_words . error ! = SUCCESS ) {
qWarning ( ) < < " wallet_ffi_resolve_public_account failed at instruction serialization: wallet FFI error " < < raw_words . error ;
return transferResultToJson ( nullptr , QStringLiteral ( " wallet_ffi_resolve_public_account: wallet FFI error " ) + QString : : number ( error ) ) ;
}
FfiProgram main_program { } ;
const uint8_t * program_elf_data = program_elf . constData ( ) ;
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 ;
QList < FfiProgram > ffi_program_dependencies ;
for ( int i = 0 ; i < program_dependencies . size ( ) ; + + i ) {
FfiProgram program { } ;
const uint8_t * program_elf_data = program_dependencies [ i ] . constData ( ) ;
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 . append ( program ) ;
}
const FfiProgram * dependencies_data = ffi_program_dependencies . constData ( ) ;
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 ,
raw_words . instruction_words ,
raw_words . instruction_words_size ,
& program_with_dependencies ,
result ,
) ;
for ( FfiAccountIdentity & acc_identity : identities_resolved ) {
wallet_ffi_free_account_identity ( & acc_identity ) ;
}
if ( error ! = SUCCESS ) {
qWarning ( ) < < " send_generic_public_transaction: wallet FFI error " < < error ;
return transferResultToJson ( nullptr , QStringLiteral ( " send_generic_public_transaction: wallet FFI error " ) + QString : : number ( error ) ) ;
}
QString resultJson = genericTransactionResultToJson ( & result , QString ( ) ) ;
wallet_ffi_free_transaction_result ( & result ) ;
return resultJson ;
}
2026-02-04 15:51:02 +01:00
// === Wallet Lifecycle ===
2026-02-20 17:59:10 +01:00
int LogosExecutionZoneWalletModule : : create_new (
2026-02-04 15:51:02 +01:00
const QString & config_path ,
const QString & storage_path ,
const QString & password
) {
2026-02-18 11:21:00 +00:00
if ( walletHandle ) {
qWarning ( ) < < " create_new: wallet is already open " ;
return INTERNAL_ERROR ;
}
2026-02-04 16:18:56 +01:00
const QByteArray config_utf8 = config_path . toUtf8 ( ) ;
const QByteArray storage_utf8 = storage_path . toUtf8 ( ) ;
const QByteArray password_utf8 = password . toUtf8 ( ) ;
2026-02-04 15:51:02 +01:00
2026-02-18 11:21:00 +00:00
walletHandle = wallet_ffi_create_new ( config_utf8 . constData ( ) , storage_utf8 . constData ( ) , password_utf8 . constData ( ) ) ;
if ( ! walletHandle ) {
qWarning ( ) < < " create_new: wallet_ffi_create_new returned null " ;
return INTERNAL_ERROR ;
}
return SUCCESS ;
2026-02-04 15:51:02 +01:00
}
2026-02-20 17:59:10 +01:00
int LogosExecutionZoneWalletModule : : open ( const QString & config_path , const QString & storage_path ) {
2026-02-18 11:21:00 +00:00
if ( walletHandle ) {
qWarning ( ) < < " open: wallet is already open " ;
return INTERNAL_ERROR ;
}
2026-02-04 16:18:56 +01:00
const QByteArray config_utf8 = config_path . toUtf8 ( ) ;
const QByteArray storage_utf8 = storage_path . toUtf8 ( ) ;
2026-02-04 15:51:02 +01:00
2026-02-18 11:21:00 +00:00
walletHandle = wallet_ffi_open ( config_utf8 . constData ( ) , storage_utf8 . constData ( ) ) ;
if ( ! walletHandle ) {
qWarning ( ) < < " open: wallet_ffi_open returned null " ;
return INTERNAL_ERROR ;
}
return SUCCESS ;
2026-02-04 15:51:02 +01:00
}
2026-02-20 17:59:10 +01:00
int 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-02-18 11:21:00 +00:00
QString LogosExecutionZoneWalletModule : : get_sequencer_addr ( ) {
char * addr = wallet_ffi_get_sequencer_addr ( walletHandle ) ;
2026-02-04 15:51:02 +01:00
if ( ! addr ) {
return { } ;
}
QString result = QString : : fromUtf8 ( addr ) ;
wallet_ffi_free_string ( addr ) ;
return result ;
}