From 848c4e3d27c60c116867f0c52e5afc36403ff996 Mon Sep 17 00:00:00 2001 From: Alejandro Cabeza Romero Date: Fri, 20 Feb 2026 18:15:25 +0100 Subject: [PATCH] Expose pinata functions. --- flake.lock | 6 +- src/i_logos_execution_zone_wallet_module.h | 19 +++ src/logos_execution_zone_wallet_module.cpp | 135 +++++++++++++++++++++ src/logos_execution_zone_wallet_module.h | 19 +++ 4 files changed, 176 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index b426f0f..0999ed6 100644 --- a/flake.lock +++ b/flake.lock @@ -350,11 +350,11 @@ "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1771420202, - "narHash": "sha256-r3lO12wvYPm6Xe7YFGK40iYe+1OID5YlGlup6RGgvs8=", + "lastModified": 1771604479, + "narHash": "sha256-DxgL4uT8+F0ALuEpENkbJ0OcyNhdFgX8Mr8tezMnZ5E=", "owner": "logos-blockchain", "repo": "lssa", - "rev": "89ce9f322a1fc4214ec818e094e6efc97be02d9c", + "rev": "bc84d5cf31b3f6967060c35a5b98618d99780ade", "type": "github" }, "original": { diff --git a/src/i_logos_execution_zone_wallet_module.h b/src/i_logos_execution_zone_wallet_module.h index faa4e96..fb4eb14 100644 --- a/src/i_logos_execution_zone_wallet_module.h +++ b/src/i_logos_execution_zone_wallet_module.h @@ -42,6 +42,25 @@ public: virtual uint64_t get_last_synced_block() = 0; virtual uint64_t get_current_block_height() = 0; + // Pinata + virtual QString claim_pinata( + const QString& pinata_account_id_hex, + const QString& winner_account_id_hex, + const QString& solution_le16_hex + ) = 0; + virtual QString 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 + ) = 0; + virtual QString claim_pinata_private_owned_not_initialized( + const QString& pinata_account_id_hex, + const QString& winner_account_id_hex, + const QString& solution_le16_hex + ) = 0; + // Operations virtual QString transfer_public( const QString& from_hex, diff --git a/src/logos_execution_zone_wallet_module.cpp b/src/logos_execution_zone_wallet_module.cpp index 4c4f604..665096d 100644 --- a/src/logos_execution_zone_wallet_module.cpp +++ b/src/logos_execution_zone_wallet_module.cpp @@ -125,6 +125,31 @@ static bool jsonToFfiPrivateAccountKeys(const QString& json, FfiPrivateAccountKe return true; } +// 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(arr.size()); + out_bytes.clear(); + out_bytes.reserve(static_cast(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; +} + LogosExecutionZoneWalletModule::LogosExecutionZoneWalletModule() = default; LogosExecutionZoneWalletModule::~LogosExecutionZoneWalletModule() { @@ -326,6 +351,116 @@ uint64_t LogosExecutionZoneWalletModule::get_current_block_height() { return block_height; } +// === 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 {}; + } + QString resultJson = ffiTransferResultToJson(result); + 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(siblings_bytes.constData()); + } + + FfiTransferResult result{}; + const WalletFfiError error = wallet_ffi_claim_pinata_private_owned_already_initialized( + walletHandle, + &pinataId, + &winnerId, + &solution, + static_cast(winner_proof_index), + siblings_ptr, + siblings_len, + &result + ); + if (error != SUCCESS) { + qWarning() << "claim_pinata_private_owned_already_initialized: wallet FFI error" << error; + return {}; + } + QString resultJson = ffiTransferResultToJson(result); + 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 {}; + } + QString resultJson = ffiTransferResultToJson(result); + wallet_ffi_free_transfer_result(&result); + return resultJson; +} + // === Operations === QString LogosExecutionZoneWalletModule::transfer_public( diff --git a/src/logos_execution_zone_wallet_module.h b/src/logos_execution_zone_wallet_module.h index 59a7f9b..0bc6c14 100644 --- a/src/logos_execution_zone_wallet_module.h +++ b/src/logos_execution_zone_wallet_module.h @@ -31,6 +31,25 @@ public: // === Logos Execution Zone Wallet === + // Pinata claiming + Q_INVOKABLE QString claim_pinata( + const QString& pinata_account_id_hex, + const QString& winner_account_id_hex, + const QString& solution_le16_hex + ) override; + Q_INVOKABLE QString 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 + ) override; + Q_INVOKABLE QString claim_pinata_private_owned_not_initialized( + const QString& pinata_account_id_hex, + const QString& winner_account_id_hex, + const QString& solution_le16_hex + ) override; + // Account Management Q_INVOKABLE QString create_account_public() override; Q_INVOKABLE QString create_account_private() override;