feat: geenric transactions rewritten into non-Qt style.

This commit is contained in:
Pravdyvy 2026-06-19 13:29:56 +03:00
parent 2adacd3df5
commit 47fe468121
4 changed files with 9513 additions and 226 deletions

9415
flake.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
inputs = {
logos-module-builder.url = "github:logos-co/logos-module-builder";
nix-bundle-lgx.url = "github:logos-co/nix-bundle-lgx";
logos-execution-zone.url = "github:logos-blockchain/lssa?rev=cf3639d8252040d13b3d4e933feb19b42c76e14a"; # v0.1.2
logos-execution-zone.url = "github:logos-blockchain/lssa?rev=62d9ba10f8f86db3a1f04b329a1bd9d5b893bf60"; # lez-core-v0.1.0
};
outputs = inputs@{ logos-module-builder, ... }:

View File

@ -55,6 +55,7 @@ constexpr auto NullifierPublicKey = "nullifier_public_key";
constexpr auto ViewingPublicKey = "viewing_public_key";
constexpr auto AccountId = "account_id";
constexpr auto IsPublic = "is_public";
constexpr auto Secrets = "secrets";
} // namespace JsonKeys
bool hexToBytes(const std::string& hex, std::vector<uint8_t>& output_bytes, int expectedLength = -1) {
@ -127,6 +128,23 @@ std::string transferResultToJson(const FfiTransferResult* result, const std::str
return obj.dump();
}
// 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();
}
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);
@ -573,8 +591,13 @@ std::string LogosExecutionZoneWalletModule::transfer_shielded(
return transferResultToJson(nullptr, "transfer_shielded: amount_le16_hex must be 32 hex characters (16 bytes)");
}
// Bandaid, I am not sure, how exactly identifiers should be used.
FfiU128 identifier {};
// Keycart not yet supported
const char *key_path = nullptr;
FfiTransferResult result{};
const WalletFfiError error = wallet_ffi_transfer_shielded(walletHandle, &fromId, &toKeys, &amount, &result);
const WalletFfiError error = wallet_ffi_transfer_shielded(walletHandle, &fromId, &toKeys, &identifier, &amount, key_path, &result);
free(const_cast<uint8_t*>(toKeys.viewing_public_key));
if (error != SUCCESS) {
fprintf(stderr, "transfer_shielded: wallet FFI error %d\n", error);
@ -637,8 +660,11 @@ std::string LogosExecutionZoneWalletModule::transfer_private(
return transferResultToJson(nullptr, "transfer_private: amount_le16_hex must be 32 hex characters (16 bytes)");
}
// Bandaid, I am not sure, how exactly identifiers should be used.
FfiU128 identifier {};
FfiTransferResult result{};
const WalletFfiError error = wallet_ffi_transfer_private(walletHandle, &fromId, &toKeys, &amount, &result);
const WalletFfiError error = wallet_ffi_transfer_private(walletHandle, &fromId, &toKeys, &identifier, &amount, &result);
free(const_cast<uint8_t*>(toKeys.viewing_public_key));
if (error != SUCCESS) {
fprintf(stderr, "transfer_private: wallet FFI error %d\n", error);
@ -666,8 +692,11 @@ std::string LogosExecutionZoneWalletModule::transfer_shielded_owned(
return transferResultToJson(nullptr, "transfer_shielded_owned: amount_le16_hex must be 32 hex characters (16 bytes)");
}
// Keycart not yet supported
const char *key_path = nullptr;
FfiTransferResult result{};
const WalletFfiError error = wallet_ffi_transfer_shielded_owned(walletHandle, &fromId, &toId, &amount, &result);
const WalletFfiError error = wallet_ffi_transfer_shielded_owned(walletHandle, &fromId, &toId, &amount, key_path, &result);
if (error != SUCCESS) {
fprintf(stderr, "transfer_shielded_owned: wallet FFI error %d\n", error);
return transferResultToJson(nullptr, "transfer_shielded_owned: wallet FFI error " + std::to_string(error));
@ -739,6 +768,269 @@ std::string LogosExecutionZoneWalletModule::register_private_account(const std::
return resultJson;
}
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;
}
// === Wallet Lifecycle ===
int64_t LogosExecutionZoneWalletModule::create_new(
@ -791,4 +1083,4 @@ std::string LogosExecutionZoneWalletModule::get_sequencer_addr() {
std::string value(addr);
wallet_ffi_free_string(addr);
return value;
}
}

View File

@ -70,6 +70,28 @@ public:
std::string register_public_account(const std::string& account_id_hex);
std::string register_private_account(const std::string& account_id_hex);
std::vector<uint8_t> authenticated_transfer_elf();
std::vector<uint8_t> token_elf();
std::vector<uint8_t> amm_elf();
std::vector<uint8_t> ata_elf();
std::string 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::string 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::string send_program_deployment_transaction(
const std::vector<uint8_t>& program_elf
);
// === Configuration ===
std::string get_sequencer_addr();