#include "token_module_impl.h" #include "token_instruction_words.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Generated by logos-module-builder. Kept out of the universal API header. #include "logos_sdk.h" extern "C" { #include "token_ffi.h" } namespace { using json = nlohmann::json; constexpr char TOKEN_PROGRAM_BIN_ENV[] = "TOKEN_PROGRAM_BIN"; constexpr char TOKEN_PROGRAM_ID_ENV[] = "TOKEN_PROGRAM_ID"; std::mutex programInfoMutex; bool tokenDebug() { static const bool enabled = std::getenv("TOKEN_DEBUG") != nullptr; return enabled; } #define TOKEN_TRACE(message) \ do { \ if (tokenDebug()) std::cerr << "[token-debug] " << message << '\n'; \ } while (false) int hexValue(char value) { if (value >= '0' && value <= '9') return value - '0'; if (value >= 'a' && value <= 'f') return value - 'a' + 10; if (value >= 'A' && value <= 'F') return value - 'A' + 10; return -1; } bool isHexLength(const std::string& value, std::size_t length) { if (value.size() != length) return false; return std::all_of(value.begin(), value.end(), [](char c) { return hexValue(c) >= 0; }); } bool isEvenHex(const std::string& value) { return value.size() % 2 == 0 && std::all_of(value.begin(), value.end(), [](char c) { return hexValue(c) >= 0; }); } std::string lowercase(std::string value) { std::transform(value.begin(), value.end(), value.begin(), [](unsigned char c) { return static_cast(std::tolower(c)); }); return value; } std::string trim(const std::string& value) { std::size_t begin = 0; std::size_t end = value.size(); while (begin < end && std::isspace(static_cast(value[begin]))) ++begin; while (end > begin && std::isspace(static_cast(value[end - 1]))) --end; return value.substr(begin, end - begin); } bool isZeroId(const std::string& value) { return value.size() == 64 && std::all_of(value.begin(), value.end(), [](char c) { return c == '0'; }); } bool isAllZero(const std::string& value) { return !value.empty() && std::all_of(value.begin(), value.end(), [](char c) { return c == '0'; }); } bool isDefaultPublicAccount(const std::string& owner, const std::string& balance, const std::string& nonce, const std::string& data) { // The execution-zone read API represents an absent public account with // Account::default(): zero owner, balance, and nonce, with no data. return isZeroId(owner) && isAllZero(balance) && isAllZero(nonce) && data.empty(); } std::string jsonString(const json& object, const char* key) { const auto it = object.find(key); return it != object.end() && it->is_string() ? it->get() : std::string(); } std::string bytesToHex(const std::uint8_t* bytes, std::size_t length) { static constexpr char digits[] = "0123456789abcdef"; std::string result; result.reserve(length * 2); for (std::size_t i = 0; i < length; ++i) { result.push_back(digits[bytes[i] >> 4]); result.push_back(digits[bytes[i] & 0x0f]); } return result; } LogosMap publicOk() { return {{"status", "ok"}, {"error", ""}}; } LogosMap publicError(const std::string& error) { return {{"status", "error"}, {"error", error}}; } template LogosMap guarded(Operation&& operation) noexcept { try { return operation(); } catch (const std::exception& error) { TOKEN_TRACE("caught exception: " << error.what()); } catch (...) { TOKEN_TRACE("caught non-standard exception"); } return publicError("backend_error"); } struct FfiResult { bool ok = false; json value; std::string error; }; FfiResult callToken(char* (*operation)(const char*), const json& request) { const std::string payload = request.dump(); std::unique_ptr response( operation(payload.c_str()), &token_free); if (!response) { TOKEN_TRACE("token_ffi returned null"); return {}; } const json document = json::parse(response.get(), nullptr, false); if (!document.is_object()) { TOKEN_TRACE("token_ffi returned malformed JSON"); return {}; } const auto ok = document.find("ok"); if (ok == document.end() || !ok->is_boolean()) return {}; if (!ok->get()) { const std::string error = jsonString(document, "error"); TOKEN_TRACE("token_ffi failure: " << error); return {false, json(), error}; } const auto value = document.find("value"); if (value == document.end() || !value->is_object()) return {}; return {true, *value, {}}; } bool isStableError(const std::string& error) { static const std::set stable = { "bad_request", "bad_amount", "invalid_account_id", "invalid_authority", "invalid_metadata_standard", "account_read_failed", "token_program_mismatch", "invalid_definition_data", "invalid_holding_data", "invalid_metadata_data", "backend_error", }; return stable.find(error) != stable.end(); } std::string ffiError(const FfiResult& result, const std::string& fallback = "backend_error") { return isStableError(result.error) ? result.error : fallback; } } // namespace std::vector TokenModuleImpl::loadTokenBinary() const { const char* path = std::getenv(TOKEN_PROGRAM_BIN_ENV); if (path == nullptr || *path == '\0') return {}; std::ifstream file(path, std::ios::binary); if (!file) return {}; return std::vector(std::istreambuf_iterator(file), std::istreambuf_iterator()); } std::string TokenModuleImpl::loadTokenProgramId() const { const char* value = std::getenv(TOKEN_PROGRAM_ID_ENV); return value == nullptr ? std::string() : trim(value); } nlohmann::json TokenModuleImpl::tokenProgramInfo() { const std::lock_guard lock(programInfoMutex); if (programInfoResolved_) { return {{"programId", programId_}, {"programIdHex", programIdHex_}}; } const std::string configured_program = loadTokenProgramId(); const bool program_id_configured = !configured_program.empty(); const char* binary_path = std::getenv(TOKEN_PROGRAM_BIN_ENV); const bool binary_configured = binary_path != nullptr && *binary_path != '\0'; const std::string configured_program_hex = program_id_configured ? normalizeAccountId(configured_program) : std::string(); if (program_id_configured && configured_program_hex.empty()) { TOKEN_TRACE("TOKEN_PROGRAM_ID is not a valid account ID"); return json(); } const std::vector binary = loadTokenBinary(); if (binary_configured && binary.empty()) { TOKEN_TRACE("TOKEN_PROGRAM_BIN is configured but unreadable"); return json(); } std::string derived_program; std::string derived_program_hex; if (!binary.empty()) { const FfiResult result = callToken( token_program_id, {{"elf", bytesToHex(binary.data(), binary.size())}}); if (!result.ok) return json(); derived_program_hex = lowercase(jsonString(result.value, "programId")); derived_program = jsonString(result.value, "programIdBase58"); if (derived_program.empty() || !isHexLength(derived_program_hex, 64) || isZeroId(derived_program_hex)) { return json(); } } if (!program_id_configured && !binary_configured) return json(); if (program_id_configured && binary_configured && configured_program_hex != derived_program_hex) { TOKEN_TRACE("TOKEN_PROGRAM_ID does not match TOKEN_PROGRAM_BIN"); return json(); } const std::string program_id_hex = program_id_configured ? configured_program_hex : derived_program_hex; const std::string program_id = binary_configured ? derived_program : modules().logos_execution_zone.account_id_to_base58(program_id_hex); if (program_id.empty() || !isHexLength(program_id_hex, 64) || isZeroId(program_id_hex)) { return json(); } // Cache successful resolution only: an early missing/unreadable // configuration may become available later during process startup. programId_ = program_id; programIdHex_ = program_id_hex; programInfoResolved_ = true; return {{"programId", programId_}, {"programIdHex", programIdHex_}}; } std::string TokenModuleImpl::normalizeAccountId(const std::string& id) { std::string normalized = trim(id); if (isHexLength(normalized, 64)) { normalized = lowercase(std::move(normalized)); return isZeroId(normalized) ? std::string() : normalized; } if (normalized.empty()) return {}; normalized = lowercase( modules().logos_execution_zone.account_id_from_base58(normalized)); return isHexLength(normalized, 64) && !isZeroId(normalized) ? normalized : std::string(); } nlohmann::json TokenModuleImpl::readPublicAccount(const std::string& account_id) { json read = {{"id", account_id}, {"status", "not_found"}}; logos::CallError call_error; const std::string raw = modules().logos_execution_zone.get_account_public(account_id, &call_error); if (!call_error.ok()) { TOKEN_TRACE("logos_execution_zone account read transport failure: " << call_error.code); read["status"] = "backend_error"; return read; } if (raw.empty()) return read; const json account = json::parse(raw, nullptr, false); if (!account.is_object()) { read["status"] = "backend_error"; return read; } std::string owner = lowercase(jsonString(account, "program_owner")); std::string balance = lowercase(jsonString(account, "balance")); std::string nonce = lowercase(jsonString(account, "nonce")); std::string data = lowercase(jsonString(account, "data")); if (!isHexLength(owner, 64) || !isHexLength(balance, 32) || !isHexLength(nonce, 32) || !isEvenHex(data)) { read["status"] = "backend_error"; return read; } if (isDefaultPublicAccount(owner, balance, nonce, data)) return read; read["status"] = "ok"; read["account"] = { {"program_owner", std::move(owner)}, {"balance", std::move(balance)}, {"nonce", std::move(nonce)}, {"data", std::move(data)}, }; return read; } nlohmann::json TokenModuleImpl::walletAccountIds() { logos::CallError call_error; const json accounts = modules().logos_execution_zone.list_accounts(&call_error); if (!call_error.ok()) { TOKEN_TRACE("logos_execution_zone account list transport failure: " << call_error.code); return json(); } if (!accounts.is_array()) return json(); std::set unique; for (const auto& account : accounts) { if (!account.is_object()) continue; const auto is_public = account.find("is_public"); if (is_public == account.end() || !is_public->is_boolean() || !is_public->get()) { continue; } const std::string id = normalizeAccountId(jsonString(account, "account_id")); if (!id.empty()) unique.insert(id); } return json(unique); } bool TokenModuleImpl::isFreshOwnedAccount(const std::string& account_id, bool& fresh, std::string& error) { const json read = readPublicAccount(account_id); if (jsonString(read, "status") == "ok") { const json info = tokenProgramInfo(); if (!info.is_object()) { error = "config_missing"; return false; } const FfiResult decoded = callToken(token_decode_holding, { {"tokenProgramId", info["programIdHex"]}, {"holding", read}, }); if (!decoded.ok) { error = ffiError(decoded); return false; } fresh = false; return true; } if (jsonString(read, "status") != "not_found") { error = "backend_error"; return false; } const json wallet_ids = walletAccountIds(); if (!wallet_ids.is_array()) { error = "backend_error"; return false; } if (std::find(wallet_ids.begin(), wallet_ids.end(), json(account_id)) == wallet_ids.end()) { error = "account_read_failed"; return false; } fresh = true; return true; } bool TokenModuleImpl::requireFreshOwnedAccount(const std::string& account_id, std::string& error) { bool fresh = false; if (!isFreshOwnedAccount(account_id, fresh, error)) return false; if (!fresh) { error = "account_read_failed"; return false; } return true; } LogosMap TokenModuleImpl::programInfo() { return guarded([&]() -> LogosMap { const json info = tokenProgramInfo(); if (!info.is_object()) return publicError("config_missing"); LogosMap result = publicOk(); result["programId"] = info["programId"]; result["programIdHex"] = info["programIdHex"]; result["networkFingerprint"] = info["programIdHex"]; return result; }); } LogosMap TokenModuleImpl::inspectAccount(const std::string& account_id, TokenOperation operation, const char* payload_key) { const json info = tokenProgramInfo(); if (!info.is_object()) return publicError("config_missing"); const std::string normalized = normalizeAccountId(account_id); if (normalized.empty()) return publicError("invalid_account_id"); const json read = readPublicAccount(normalized); const std::string read_status = jsonString(read, "status"); if (read_status == "backend_error") return publicError("backend_error"); if (read_status != "ok") return publicError("account_read_failed"); json request = {{"tokenProgramId", info["programIdHex"]}}; request[payload_key] = read; const FfiResult decoded = callToken(operation, request); if (!decoded.ok) return publicError(ffiError(decoded)); LogosMap result = publicOk(); result[payload_key] = decoded.value; return result; } LogosMap TokenModuleImpl::inspectDefinition(const std::string& definition_id) { return guarded([&]() { return inspectAccount(definition_id, token_decode_definition, "definition"); }); } LogosMap TokenModuleImpl::inspectHolding(const std::string& holding_id) { return guarded([&]() { return inspectAccount(holding_id, token_decode_holding, "holding"); }); } LogosMap TokenModuleImpl::inspectMetadata(const std::string& metadata_id) { return guarded([&]() { return inspectAccount(metadata_id, token_decode_metadata, "metadata"); }); } LogosMap TokenModuleImpl::walletTokenAccounts() { return guarded([&]() -> LogosMap { const json info = tokenProgramInfo(); if (!info.is_object()) return publicError("config_missing"); const std::string program_id = jsonString(info, "programIdHex"); const json ids = walletAccountIds(); if (!ids.is_array()) return publicError("backend_error"); json accounts = json::array(); for (const auto& id_value : ids) { if (!id_value.is_string()) continue; const std::string id = id_value.get(); const json read = readPublicAccount(id); if (jsonString(read, "status") != "ok") continue; const auto account = read.find("account"); if (account == read.end() || !account->is_object() || lowercase(jsonString(*account, "program_owner")) != program_id) { continue; } const FfiResult decoded = callToken(token_decode_account, { {"tokenProgramId", program_id}, {"account", read}, }); if (!decoded.ok || !isHexLength(jsonString(decoded.value, "accountIdHex"), 64)) { continue; } accounts.push_back(decoded.value); } std::sort(accounts.begin(), accounts.end(), [](const json& left, const json& right) { return lowercase(jsonString(left, "accountIdHex")) < lowercase(jsonString(right, "accountIdHex")); }); LogosMap result = publicOk(); result["accounts"] = std::move(accounts); return result; }); } LogosMap TokenModuleImpl::submitPlan(const nlohmann::json& plan) { const auto account_ids_it = plan.find("accountIds"); const auto signers_it = plan.find("signingRequirements"); const auto instruction_it = plan.find("instruction"); const std::string program_id = lowercase(jsonString(plan, "programId")); if (account_ids_it == plan.end() || signers_it == plan.end() || instruction_it == plan.end() || !isHexLength(program_id, 64)) { return publicError("backend_error"); } const std::vector account_ids = account_ids_it->get>(); const std::vector signers = signers_it->get>(); const std::vector instruction = token_module::detail::jsonInstructionLeBytes(*instruction_it); if (account_ids.empty() || account_ids.size() != signers.size() || instruction.empty() || std::any_of(account_ids.begin(), account_ids.end(), [](const std::string& id) { return !isHexLength(id, 64) || isZeroId(id); })) { return publicError("backend_error"); } logos::CallError call_error; const std::string raw = modules().logos_execution_zone.send_generic_public_transaction( account_ids, signers, instruction, program_id, &call_error); if (!call_error.ok()) { TOKEN_TRACE("logos_execution_zone submission transport failure: " << call_error.code); return publicError("wallet_submission_failed"); } const json reply = json::parse(raw, nullptr, false); if (!reply.is_object()) return publicError("wallet_submission_failed"); const auto success = reply.find("success"); const std::string transaction_id = jsonString(reply, "tx_hash"); if (success == reply.end() || !success->is_boolean() || !success->get() || transaction_id.empty()) { return publicError("wallet_submission_failed"); } LogosMap result = publicOk(); result["transactionId"] = transaction_id; return result; } bool TokenModuleImpl::normalizeAuthority(const std::string& authority, std::string& normalized) { const std::string sentinel = lowercase(trim(authority)); if (sentinel == "none" || sentinel == "self") { normalized = sentinel; return true; } normalized = normalizeAccountId(authority); return !normalized.empty(); } LogosMap TokenModuleImpl::planAndSubmit(TokenOperation planner, nlohmann::json request) { const json info = tokenProgramInfo(); if (!info.is_object()) return publicError("config_missing"); const std::string configured_program = jsonString(info, "programIdHex"); request["tokenProgramId"] = configured_program; const FfiResult result = callToken(planner, request); if (!result.ok) return publicError(ffiError(result)); if (lowercase(jsonString(result.value, "programId")) != configured_program) { return publicError("backend_error"); } return submitPlan(result.value); } LogosMap TokenModuleImpl::createFungible(const std::string& definition_target_id, const std::string& holding_target_id, const std::string& name, const nlohmann::json& total_supply_raw, const std::string& mint_authority) { return guarded([&]() -> LogosMap { const std::string definition = normalizeAccountId(definition_target_id); const std::string holding = normalizeAccountId(holding_target_id); if (definition.empty() || holding.empty()) return publicError("invalid_account_id"); std::string error; if (!requireFreshOwnedAccount(definition, error) || !requireFreshOwnedAccount(holding, error)) { return publicError(error); } std::string authority; if (!normalizeAuthority(mint_authority, authority)) { return publicError("invalid_authority"); } return planAndSubmit(token_create_fungible_plan, { {"definitionTargetId", definition}, {"holdingTargetId", holding}, {"name", name}, {"totalSupplyRaw", total_supply_raw}, {"mintAuthority", authority}, }); }); } LogosMap TokenModuleImpl::createFungibleWithMetadata( const std::string& definition_target_id, const std::string& holding_target_id, const std::string& metadata_target_id, const std::string& name, const nlohmann::json& total_supply_raw, const std::string& mint_authority, const std::string& metadata_standard, const std::string& uri, const std::string& creators) { return guarded([&]() -> LogosMap { const std::string definition = normalizeAccountId(definition_target_id); const std::string holding = normalizeAccountId(holding_target_id); const std::string metadata = normalizeAccountId(metadata_target_id); if (definition.empty() || holding.empty() || metadata.empty()) { return publicError("invalid_account_id"); } std::string error; if (!requireFreshOwnedAccount(definition, error) || !requireFreshOwnedAccount(holding, error) || !requireFreshOwnedAccount(metadata, error)) { return publicError(error); } std::string authority; if (!normalizeAuthority(mint_authority, authority)) { return publicError("invalid_authority"); } return planAndSubmit(token_create_fungible_with_metadata_plan, { {"definitionTargetId", definition}, {"holdingTargetId", holding}, {"metadataTargetId", metadata}, {"name", name}, {"totalSupplyRaw", total_supply_raw}, {"mintAuthority", authority}, {"metadataStandard", metadata_standard}, {"uri", uri}, {"creators", creators}, }); }); } LogosMap TokenModuleImpl::createNonFungible( const std::string& definition_target_id, const std::string& master_holding_target_id, const std::string& metadata_target_id, const std::string& name, const nlohmann::json& printable_supply_raw, const std::string& metadata_standard, const std::string& uri, const std::string& creators) { return guarded([&]() -> LogosMap { const std::string definition = normalizeAccountId(definition_target_id); const std::string master = normalizeAccountId(master_holding_target_id); const std::string metadata = normalizeAccountId(metadata_target_id); if (definition.empty() || master.empty() || metadata.empty()) { return publicError("invalid_account_id"); } std::string error; if (!requireFreshOwnedAccount(definition, error) || !requireFreshOwnedAccount(master, error) || !requireFreshOwnedAccount(metadata, error)) { return publicError(error); } return planAndSubmit(token_create_non_fungible_plan, { {"definitionTargetId", definition}, {"masterHoldingTargetId", master}, {"metadataTargetId", metadata}, {"name", name}, {"printableSupplyRaw", printable_supply_raw}, {"metadataStandard", metadata_standard}, {"uri", uri}, {"creators", creators}, }); }); } LogosMap TokenModuleImpl::initializeHolding(const std::string& definition_id, const std::string& holding_target_id) { return guarded([&]() -> LogosMap { const std::string definition = normalizeAccountId(definition_id); const std::string holding = normalizeAccountId(holding_target_id); if (definition.empty() || holding.empty()) return publicError("invalid_account_id"); std::string error; if (!requireFreshOwnedAccount(holding, error)) return publicError(error); return planAndSubmit(token_initialize_holding_plan, { {"definitionId", definition}, {"holdingTargetId", holding}, }); }); } LogosMap TokenModuleImpl::transfer(const std::string& sender_holding_id, const std::string& recipient_holding_id, const nlohmann::json& amount_raw) { return guarded([&]() -> LogosMap { const std::string sender = normalizeAccountId(sender_holding_id); const std::string recipient = normalizeAccountId(recipient_holding_id); if (sender.empty() || recipient.empty()) return publicError("invalid_account_id"); bool recipient_fresh = false; std::string error; if (!isFreshOwnedAccount(recipient, recipient_fresh, error)) { return publicError(error); } return planAndSubmit(token_transfer_plan, { {"senderHoldingId", sender}, {"recipientHoldingId", recipient}, {"amountRaw", amount_raw}, {"recipientIsFresh", recipient_fresh}, }); }); } LogosMap TokenModuleImpl::burn(const std::string& definition_id, const std::string& holding_id, const nlohmann::json& amount_raw) { return guarded([&]() -> LogosMap { const std::string definition = normalizeAccountId(definition_id); const std::string holding = normalizeAccountId(holding_id); if (definition.empty() || holding.empty()) return publicError("invalid_account_id"); return planAndSubmit(token_burn_plan, { {"definitionId", definition}, {"holdingId", holding}, {"amountRaw", amount_raw}, }); }); } LogosMap TokenModuleImpl::mint(const std::string& definition_id, const std::string& holding_id, const nlohmann::json& amount_raw) { return guarded([&]() -> LogosMap { const std::string definition = normalizeAccountId(definition_id); const std::string holding = normalizeAccountId(holding_id); if (definition.empty() || holding.empty()) return publicError("invalid_account_id"); bool holding_fresh = false; std::string error; if (!isFreshOwnedAccount(holding, holding_fresh, error)) return publicError(error); return planAndSubmit(token_mint_plan, { {"definitionId", definition}, {"holdingId", holding}, {"amountRaw", amount_raw}, {"holdingIsFresh", holding_fresh}, }); }); } LogosMap TokenModuleImpl::mintWithAuthority(const std::string& definition_id, const std::string& holding_id, const std::string& authority_id, const nlohmann::json& amount_raw) { return guarded([&]() -> LogosMap { const std::string definition = normalizeAccountId(definition_id); const std::string holding = normalizeAccountId(holding_id); const std::string authority = normalizeAccountId(authority_id); if (definition.empty() || holding.empty()) return publicError("invalid_account_id"); if (authority.empty()) return publicError("invalid_authority"); bool holding_fresh = false; std::string error; if (!isFreshOwnedAccount(holding, holding_fresh, error)) return publicError(error); return planAndSubmit(token_mint_with_authority_plan, { {"definitionId", definition}, {"holdingId", holding}, {"authorityId", authority}, {"amountRaw", amount_raw}, {"holdingIsFresh", holding_fresh}, }); }); } LogosMap TokenModuleImpl::setAuthority(const std::string& definition_id, const std::string& new_authority) { return guarded([&]() -> LogosMap { const std::string definition = normalizeAccountId(definition_id); if (definition.empty()) return publicError("invalid_account_id"); std::string authority; if (!normalizeAuthority(new_authority, authority)) { return publicError("invalid_authority"); } return planAndSubmit(token_set_authority_plan, { {"definitionId", definition}, {"newAuthority", authority}, }); }); } LogosMap TokenModuleImpl::setAuthorityWithAuthority( const std::string& definition_id, const std::string& authority_id, const std::string& new_authority) { return guarded([&]() -> LogosMap { const std::string definition = normalizeAccountId(definition_id); const std::string current_authority = normalizeAccountId(authority_id); if (definition.empty()) return publicError("invalid_account_id"); if (current_authority.empty()) return publicError("invalid_authority"); std::string next_authority; if (!normalizeAuthority(new_authority, next_authority)) { return publicError("invalid_authority"); } return planAndSubmit(token_set_authority_with_authority_plan, { {"definitionId", definition}, {"authorityId", current_authority}, {"newAuthority", next_authority}, }); }); } LogosMap TokenModuleImpl::printNft(const std::string& master_holding_id, const std::string& printed_holding_target_id) { return guarded([&]() -> LogosMap { const std::string master = normalizeAccountId(master_holding_id); const std::string printed = normalizeAccountId(printed_holding_target_id); if (master.empty() || printed.empty()) return publicError("invalid_account_id"); std::string error; if (!requireFreshOwnedAccount(printed, error)) return publicError(error); return planAndSubmit(token_print_nft_plan, { {"masterHoldingId", master}, {"printedHoldingTargetId", printed}, }); }); }