// DragonX Wallet - ImGui Edition // Copyright 2024-2026 The Hush Developers // Released under the GPLv3 #include "lite_client_bridge.h" #include "lite_owned_string.h" #ifndef DRAGONX_ENABLE_LITE_BACKEND #define DRAGONX_ENABLE_LITE_BACKEND 0 #endif #if DRAGONX_ENABLE_LITE_BACKEND extern "C" { bool litelib_wallet_exists(const char* chain_name); char* litelib_initialize_new(bool dangerous, const char* server); char* litelib_initialize_new_from_phrase(bool dangerous, const char* server, const char* seed, unsigned long long birthday, unsigned long long number, bool overwrite); char* litelib_initialize_existing(bool dangerous, const char* server); char* litelib_execute(const char* command, const char* args); void litelib_rust_free_string(char* value); bool litelib_check_server_online(const char* server); void litelib_shutdown(); } #endif #include namespace dragonx { namespace wallet { namespace { bool hasRequiredApi(const LiteClientBridgeApi& api) { return api.walletExists && api.initializeNew && api.initializeNewFromPhrase && api.initializeExisting && api.execute && api.freeString && api.checkServerOnline && api.shutdown; } #if DRAGONX_ENABLE_LITE_BACKEND LiteClientBridgeApi linkedSdxlApi() { return LiteClientBridgeApi{ &litelib_wallet_exists, &litelib_initialize_new, &litelib_initialize_new_from_phrase, &litelib_initialize_existing, &litelib_execute, &litelib_rust_free_string, &litelib_check_server_online, &litelib_shutdown }; } #endif } // namespace LiteClientBridge::LiteClientBridge(LiteClientBridgeApi api, std::string unavailableReason) : api_(api), unavailableReason_(std::move(unavailableReason)) { } LiteClientBridge LiteClientBridge::unavailable(std::string reason) { return LiteClientBridge({}, std::move(reason)); } LiteClientBridge LiteClientBridge::fromApi(LiteClientBridgeApi api) { if (!hasRequiredApi(api)) { return unavailable("lite client bridge API is incomplete"); } return LiteClientBridge(api, {}); } LiteClientBridge LiteClientBridge::linkedSdxl() { #if DRAGONX_ENABLE_LITE_BACKEND return fromApi(linkedSdxlApi()); #else return unavailable("lite backend is not linked"); #endif } LiteClientBridge::LiteClientBridge(LiteClientBridge&& other) noexcept : api_(other.api_), unavailableReason_(std::move(other.unavailableReason_)), shutdownCalled_(other.shutdownCalled_) { other.api_ = {}; other.shutdownCalled_ = true; } LiteClientBridge& LiteClientBridge::operator=(LiteClientBridge&& other) noexcept { if (this == &other) return *this; shutdown(); api_ = other.api_; unavailableReason_ = std::move(other.unavailableReason_); shutdownCalled_ = other.shutdownCalled_; other.api_ = {}; other.shutdownCalled_ = true; return *this; } LiteClientBridge::~LiteClientBridge() { shutdown(); } bool LiteClientBridge::available() const { return hasRequiredApi(api_); } bool LiteClientBridge::walletExists(const std::string& chainName) const { if (!available()) return false; return api_.walletExists(chainName.c_str()); } bool LiteClientBridge::checkServerOnline(const std::string& server) const { if (!available()) return false; return api_.checkServerOnline(server.c_str()); } LiteBridgeStringResult LiteClientBridge::initializeNew(bool dangerous, const std::string& server) { if (!available()) return unavailableResult(); return takeOwnedString(api_.initializeNew(dangerous, server.c_str())); } LiteBridgeStringResult LiteClientBridge::initializeNewFromPhrase(bool dangerous, const std::string& server, const std::string& seed, unsigned long long birthday, unsigned long long account, bool overwrite) { if (!available()) return unavailableResult(); return takeOwnedString(api_.initializeNewFromPhrase( dangerous, server.c_str(), seed.c_str(), birthday, account, overwrite)); } LiteBridgeStringResult LiteClientBridge::initializeExisting(bool dangerous, const std::string& server) { if (!available()) return unavailableResult(); return takeOwnedString(api_.initializeExisting(dangerous, server.c_str())); } LiteBridgeStringResult LiteClientBridge::execute(const std::string& command, const std::string& args) { if (!available()) return unavailableResult(); if (command.empty()) return {false, {}, "lite command is empty"}; return takeOwnedString(api_.execute(command.c_str(), args.c_str())); } void LiteClientBridge::shutdown() { if (shutdownCalled_) return; shutdownCalled_ = true; if (available()) api_.shutdown(); } LiteBridgeStringResult LiteClientBridge::unavailableResult() const { return {false, {}, unavailableReason_.empty() ? "lite backend is unavailable" : unavailableReason_}; } LiteBridgeStringResult LiteClientBridge::takeOwnedString(char* rawValue) const { return liteBridgeRuntimeTakeOwnedString(rawValue, api_.freeString); } } // namespace wallet } // namespace dragonx