diff --git a/doctests/logos-execution-zone-runtime.test.yaml b/doctests/logos-execution-zone-runtime.test.yaml index 7be19af..a0a469a 100644 --- a/doctests/logos-execution-zone-runtime.test.yaml +++ b/doctests/logos-execution-zone-runtime.test.yaml @@ -201,8 +201,6 @@ sections: code_block: "logoscore module-info lez_core" expect_contains: - "lez_core" - - "account_id_to_base58" - - "account_id_from_base58" - title: "Read the module name" text: | @@ -220,7 +218,7 @@ sections: run: "./logos/bin/logoscore call lez_core version" code_block: "logoscore call lez_core version" expect_contains: - - '"result":"0.2.0"' + - '"result":"0.3.0"' - title: "Encode an account id to base58" text: | diff --git a/flake.lock b/flake.lock index d6cc145..dfdcc2d 100644 --- a/flake.lock +++ b/flake.lock @@ -1276,11 +1276,11 @@ ] }, "locked": { - "lastModified": 1782492700, - "narHash": "sha256-Cfu9C6wMubyWTDLEh738rfCt3CuI91BZNWLj2GfTXAY=", + "lastModified": 1782844386, + "narHash": "sha256-8WWaS5BakBGLcsLlZPs9QWG5URwmRMV/Wj/Zny7vLLQ=", "owner": "logos-co", "repo": "logos-cpp-sdk", - "rev": "350a2891e60a40aba93f273d85e8accb4803ac29", + "rev": "d12a7bbb45d7d05f003b5d746a6c4dbc9df28315", "type": "github" }, "original": { @@ -2716,17 +2716,17 @@ "rust-rapidsnark": "rust-rapidsnark" }, "locked": { - "lastModified": 1782820738, - "narHash": "sha256-OnXBx3nD/r7vCzZwh/RXmoqbtNF9rG+ZZsWXPsXoOzk=", + "lastModified": 1782922431, + "narHash": "sha256-loCudmjk5qD12UqgiS7lyUc2UpTDzNpH1y0e8qojkNs=", "owner": "logos-blockchain", "repo": "logos-execution-zone", - "rev": "a58fbce2ff48c58b7bb5001b1a27e64b9596ee3a", + "rev": "571f35b3849c889f893109fd2b9dad040f0a3b57", "type": "github" }, "original": { "owner": "logos-blockchain", "repo": "logos-execution-zone", - "rev": "a58fbce2ff48c58b7bb5001b1a27e64b9596ee3a", + "rev": "571f35b3849c889f893109fd2b9dad040f0a3b57", "type": "github" } }, @@ -3857,11 +3857,11 @@ "rust-overlay": "rust-overlay_3" }, "locked": { - "lastModified": 1782496890, - "narHash": "sha256-jm3NQ0BZ5qnUs/boE1vTil+mGbbp+Wix0ggl1HzR2gw=", + "lastModified": 1782909437, + "narHash": "sha256-0SiWr9+mP/BnK5ck0Qia0OmV7lL+vFTpzdum97VHPmw=", "owner": "logos-co", "repo": "logos-module-builder", - "rev": "92ef691ea72844134f6c68fb447d37f855fc9690", + "rev": "6ef42ea8661121831ece79e6b702e27ac1cf46e7", "type": "github" }, "original": { @@ -16819,11 +16819,11 @@ ] }, "locked": { - "lastModified": 1782490644, - "narHash": "sha256-IRHFIBa/+a10tVNEexm6DDZ0JPF8YQgUbxWoNwIytt4=", + "lastModified": 1782842011, + "narHash": "sha256-2PZuDfaLe/CAs3W1vD0XVeR6gu18qG64jHimleelZns=", "owner": "logos-co", "repo": "logos-protocol", - "rev": "d5d58e7e230768505c683150f651358612abd442", + "rev": "976bc7a9a0563e5513617f04a47e7f87f40faeaa", "type": "github" }, "original": { @@ -17687,17 +17687,17 @@ ] }, "locked": { - "lastModified": 1782045655, - "narHash": "sha256-fprp1M+5opx3nfqAW+2HKcRUQyc+zqxsOxdNvpJFFv0=", + "lastModified": 1782844668, + "narHash": "sha256-Ri1H6TuhSKgiW9wVRhBCjXtEwrvH1j8QZU1ciS2JI0c=", "owner": "logos-co", "repo": "logos-rust-sdk", - "rev": "9957a9dd81c38c27e7021b623709129d3a4b7476", + "rev": "270e4cf687896d501ed73c1409ea4157cc8a5b54", "type": "github" }, "original": { "owner": "logos-co", "repo": "logos-rust-sdk", - "rev": "9957a9dd81c38c27e7021b623709129d3a4b7476", + "rev": "270e4cf687896d501ed73c1409ea4157cc8a5b54", "type": "github" } }, @@ -17925,11 +17925,11 @@ ] }, "locked": { - "lastModified": 1782495806, - "narHash": "sha256-coe3A0+42ABOz3XRBxVuoYY3dlgidl17N19jChIKQJw=", + "lastModified": 1782891989, + "narHash": "sha256-jnP4z1Y5vX/0mYFbJiAdklMS+a0e5orkw+3a4dSEIv0=", "owner": "logos-co", "repo": "logos-standalone-app", - "rev": "473a201a65c286538408aaef36a692f0020bc472", + "rev": "c87bbf4cceec06cba7de00e84dd4b09b8b05c4be", "type": "github" }, "original": { @@ -18562,11 +18562,11 @@ ] }, "locked": { - "lastModified": 1782494049, - "narHash": "sha256-wcWVA8NGvTZrO8tCGqVe5UB9uIDEP+qsxlNCyvHneVc=", + "lastModified": 1782891750, + "narHash": "sha256-0mz3BuhiVEUwb55h227aVe/Hlk/2UgZRhAaRyT50J3M=", "owner": "logos-co", "repo": "logos-view-module-runtime", - "rev": "70f219a24847d79fa74e7a93d09798b2cc580253", + "rev": "7cb233277297f7e6fb317c9734a0c40253d8e8fd", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index ae5aa92..c3c4b97 100644 --- a/flake.nix +++ b/flake.nix @@ -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/logos-execution-zone?rev=a58fbce2ff48c58b7bb5001b1a27e64b9596ee3a"; # v0.2.0 + logos-execution-zone.url = "github:logos-blockchain/logos-execution-zone?rev=571f35b3849c889f893109fd2b9dad040f0a3b57"; }; outputs = inputs@{ logos-module-builder, ... }: diff --git a/metadata.json b/metadata.json index 4bbc267..ac50512 100644 --- a/metadata.json +++ b/metadata.json @@ -1,7 +1,7 @@ { "name": "lez_core", "display_name": "LEZ Core Module", - "version": "0.2.0", + "version": "0.3.0", "description": "Logos Execution Zone Core Module for Logos Core", "author": "Logos Blockchain Team", "type": "core", diff --git a/src/lez_core_module.cpp b/src/lez_core_module.cpp index d49c373..dbd7290 100644 --- a/src/lez_core_module.cpp +++ b/src/lez_core_module.cpp @@ -277,7 +277,7 @@ std::string LEZCoreModule::name() const { } std::string LEZCoreModule::version() const { - return "0.2.0"; + return "0.3.0"; } // === Account Management === @@ -1212,4 +1212,99 @@ std::string LEZCoreModule::get_sequencer_addr() { std::string value(addr); wallet_ffi_free_string(addr); return value; +} + +// === Labels === + +bool LEZCoreModule::check_label_available(const std::string& label) { + const char* label_c = label.c_str(); + + LabelAvailability label_check = wallet_ffi_check_label_available( + walletHandle, + label_c + ); + + if (label_check.error != SUCCESS) { + fprintf(stderr, "check_label_available: wallet FFI error %d\n", label_check.error); + return false; + } + + return label_check.is_available; +} + +int64_t LEZCoreModule::add_label(const std::string& label, const std::string& account_id_hex, bool is_private) { + const char* label_c = label.c_str(); + + FfiBytes32 id{}; + if (!hexToBytes32(account_id_hex, &id)) { + fprintf(stderr, "wallet_ffi_add_label: invalid account_id_hex"); + return WalletFfiError::INVALID_ACCOUNT_ID; + } + + FfiAccountIdWithPrivacy acc_id_with_privacy = { id, is_private }; + + WalletFfiError error = wallet_ffi_add_label(walletHandle, label_c, acc_id_with_privacy); + if (error != SUCCESS) { + fprintf(stderr, "wallet_ffi_add_label failed : wallet FFI error %d\n", error); + } + + return SUCCESS; +} + +std::string LEZCoreModule::resolve_label(const std::string& label) { + const char* label_c = label.c_str(); + + AccountIdResolvedFromLabel acc_id_res = wallet_ffi_resolve_label( + walletHandle, + label_c + ); + + if (acc_id_res.error != SUCCESS) { + fprintf(stderr, "wallet_ffi_resolve_label failed : wallet FFI error %d\n", acc_id_res.error); + return {}; + } + + std::string hexed_account_id = bytes32ToHex(acc_id_res.account_id.account_id); + + if (acc_id_res.account_id.is_private) { + return "Private/" + hexed_account_id; + } else { + return "Public/" + hexed_account_id; + } +} + +std::vector LEZCoreModule::get_all_labels_for_account(const std::string& account_id_hex, bool is_private) { + FfiAccountIdWithPrivacy acc_id_with_privacy; + + FfiBytes32 id{}; + if (!hexToBytes32(account_id_hex, &id)) { + fprintf(stderr, "get_all_labels_for_account: invalid account_id_hex"); + return {}; + } + + acc_id_with_privacy.account_id = id; + acc_id_with_privacy.is_private = is_private; + + LabelList label_list = wallet_ffi_get_all_labels_for_account(walletHandle, acc_id_with_privacy); + + if (label_list.error != SUCCESS) { + fprintf(stderr, "wallet_ffi_get_all_labels_for_account failed : wallet FFI error %d\n", label_list.error); + return {}; + } + + std::vector result; + result.reserve(label_list.labels_size); + + for (uintptr_t i = 0; i < label_list.labels_size; ++i) { + result.emplace_back(label_list.labels_data[i]); + } + + WalletFfiError err = wallet_ffi_free_label_list(&label_list); + + if (err != SUCCESS) { + fprintf(stderr, "wallet_ffi_free_label_list failed : wallet FFI error %d\n", err); + return {}; + } + + return result; } \ No newline at end of file diff --git a/src/lez_core_module.h b/src/lez_core_module.h index 4c82286..4a1059c 100644 --- a/src/lez_core_module.h +++ b/src/lez_core_module.h @@ -92,6 +92,12 @@ public: // === Configuration === std::string get_sequencer_addr(); + // === Labels === + bool check_label_available(const std::string& label); + int64_t add_label(const std::string& label, const std::string& account_id_hex, bool is_private); + std::string resolve_label(const std::string& label); + std::vector get_all_labels_for_account(const std::string& account_id_hex, bool is_private); + private: WalletHandle* walletHandle = nullptr; }; diff --git a/tests/mocks/mock_wallet_ffi.cpp b/tests/mocks/mock_wallet_ffi.cpp index a466ed0..421b272 100644 --- a/tests/mocks/mock_wallet_ffi.cpp +++ b/tests/mocks/mock_wallet_ffi.cpp @@ -533,4 +533,80 @@ char* wallet_ffi_get_sequencer_addr(WalletHandle*) { return strdup((addr && *addr) ? addr : "127.0.0.1:3000"); } +// === Labels === + +LabelAvailability wallet_ffi_check_label_available(WalletHandle *handle, const char *label) { + LOGOS_CMOCK_RECORD("wallet_ffi_check_label_available"); + const int err = LOGOS_CMOCK_RETURN(int, "wallet_ffi_check_label_available"); + + LabelAvailability label_availablility; + + if (err == 0) { + label_availablility.is_available = true; + } else { + label_availablility.is_available = false; + } + + label_availablility.error = static_cast(err); + + return label_availablility; +} + +WalletFfiError wallet_ffi_add_label(WalletHandle *handle, const char *label, FfiAccountIdWithPrivacy account_id_with_privacy) { + LOGOS_CMOCK_RECORD("wallet_ffi_add_label"); + const int err = LOGOS_CMOCK_RETURN(int, "wallet_ffi_add_label"); + return static_cast(err); +} + +AccountIdResolvedFromLabel wallet_ffi_resolve_label(WalletHandle *handle, const char *label) { + LOGOS_CMOCK_RECORD("wallet_ffi_resolve_label"); + const int err = LOGOS_CMOCK_RETURN(int, "wallet_ffi_resolve_label"); + FfiAccountIdWithPrivacy acc_id_with_privacy; + AccountIdResolvedFromLabel acc_id_res; + + if (err == 0) { + const uint8_t value = static_cast(LOGOS_CMOCK_RETURN(int, "get_acc_id_associated_with_label")); + for (int i = 0; i < 32; ++i) { + acc_id_with_privacy.account_id.data[i] = value; + } + } + + acc_id_with_privacy.is_private = false; + + acc_id_res.account_id = acc_id_with_privacy; + acc_id_res.error = static_cast(err); + + return acc_id_res; +} + +LabelList wallet_ffi_get_all_labels_for_account(WalletHandle *handle, FfiAccountIdWithPrivacy account_id_with_privacy) { + LOGOS_CMOCK_RECORD("wallet_ffi_get_all_labels_for_account"); + const int err = LOGOS_CMOCK_RETURN(int, "wallet_ffi_get_all_labels_for_account"); + + LabelList label_list; + + if (err == 0) { + static std::vector labelsData = { "Label1", "Label2" }; + + label_list.labels_data = labelsData.data(); + label_list.labels_size = labelsData.size(); + } else { + label_list.labels_data = nullptr; + label_list.labels_size = 0; + } + + label_list.error = static_cast(err); + + return label_list; +} + +WalletFfiError wallet_ffi_free_label_list(LabelList *label_list) { + LOGOS_CMOCK_RECORD("wallet_ffi_free_label_list"); + if (label_list && label_list->labels_data) { + free(const_cast(label_list->labels_data)); + label_list->labels_data = nullptr; + label_list->labels_size = 0; + } +} + } // extern "C" diff --git a/tests/stubs/wallet_ffi.h b/tests/stubs/wallet_ffi.h index f90f5c0..4204b15 100644 --- a/tests/stubs/wallet_ffi.h +++ b/tests/stubs/wallet_ffi.h @@ -21,6 +21,7 @@ typedef enum WalletFfiError { INTERNAL_ERROR = 1, INVALID_INPUT = 2, NOT_FOUND = 3, + INVALID_ACCOUNT_ID = 4 } WalletFfiError; // Opaque wallet handle. @@ -167,6 +168,27 @@ typedef struct FfiCreateWalletOutput { char *mnemonic; } FfiCreateWalletOutput; +typedef struct LabelAvailability { + bool is_available; + enum WalletFfiError error; +} LabelAvailability; + +typedef struct FfiAccountIdWithPrivacy { + struct FfiBytes32 account_id; + bool is_private; +} FfiAccountIdWithPrivacy; + +typedef struct AccountIdResolvedFromLabel { + struct FfiAccountIdWithPrivacy account_id; + enum WalletFfiError error; +} AccountIdResolvedFromLabel; + +typedef struct LabelList { + const char **labels_data; + uintptr_t labels_size; + enum WalletFfiError error; +} LabelList; + // === Lifecycle === FfiCreateWalletOutput wallet_ffi_create_new(const char* config_path, const char* storage_path, const char* password); @@ -317,6 +339,23 @@ WalletFfiError wallet_ffi_vault_claim_private( char* wallet_ffi_get_sequencer_addr(WalletHandle* handle); +// === Labels === + +LabelAvailability wallet_ffi_check_label_available(WalletHandle *handle, + const char *label); + +WalletFfiError wallet_ffi_add_label(WalletHandle *handle, + const char *label, + FfiAccountIdWithPrivacy account_id_with_privacy); + +AccountIdResolvedFromLabel wallet_ffi_resolve_label(WalletHandle *handle, + const char *label); + +LabelList wallet_ffi_get_all_labels_for_account(WalletHandle *handle, + FfiAccountIdWithPrivacy account_id_with_privacy); + +WalletFfiError wallet_ffi_free_label_list(LabelList *label_list); + #ifdef __cplusplus } #endif diff --git a/tests/test_lez_core.cpp b/tests/test_lez_core.cpp index de812db..a709e51 100644 --- a/tests/test_lez_core.cpp +++ b/tests/test_lez_core.cpp @@ -29,7 +29,7 @@ static nlohmann::json parseObject(const std::string& json) { LOGOS_TEST(name_and_version) { LEZCoreModule module; LOGOS_ASSERT_EQ(module.name(), std::string("lez_core")); - LOGOS_ASSERT_EQ(module.version(), std::string("0.2.0")); + LOGOS_ASSERT_EQ(module.version(), std::string("0.3.0")); } // ============================================================================