#pragma once #include "lite_client_bridge.h" #include "lite_connection_service.h" #include "lite_result_parsers.h" #include "lite_sync_service.h" #include "wallet_backend.h" #include "wallet_capabilities.h" #include #include #include #include namespace dragonx::wallet { enum class LiteWalletGatewayCommand { Info, Height, Balance, Addresses, Notes, List, }; enum class LiteWalletGatewayAvailability { Ready, UnsupportedBuild, BackendUnavailable, BridgeUnavailable, BridgeCallsDisabled, NoUsableServer, }; struct LiteWalletGatewayRequest { LiteWalletGatewayCommand command = LiteWalletGatewayCommand::Info; std::string serverUrl; }; struct LiteWalletGatewayPlan { bool ok = false; LiteWalletGatewayCommand command = LiteWalletGatewayCommand::Info; LiteServerEndpoint server; std::size_t serverIndex = 0; bool customServer = false; bool bridgeExecutionAllowed = false; std::string commandName; std::string args; std::string error; }; struct LiteWalletGatewayCommandResult { bool ok = false; bool attempted = false; bool bridgeAccepted = false; LiteWalletGatewayPlan plan; LiteResultParserError parserError = LiteResultParserError::None; bool backendError = false; // bridge call failed, or the reply was not JSON (the backend's plain-text sync error) WalletBackendStatus status; std::string bridgeResponseRedacted = ""; std::string error; LiteInfoResponse info; LiteHeightResponse height; LiteBalanceResponse balance; LiteAddressesResponse addresses; LiteNotesResponse notes; LiteTransactionsResponse transactions; }; struct LiteWalletRefreshRequest { std::string serverUrl; bool includeInfo = true; bool includeHeight = true; bool includeBalance = true; bool includeAddresses = true; bool includeNotes = true; bool includeTransactions = true; bool haveSyncStatus = false; LiteSyncStatusResponse syncStatus; // Optional cooperative cancel, consulted before every backend command; returning false ends the refresh early // (result.cancelled, model discarded by the caller). std::function keepGoing; // Skip the remaining server-bound commands (info/balance/notes/list) once one returned a backend error: each // `balance`/`notes`/`list` runs do_sync, which costs ~62 s of retry back-off against a refusing server. bool stopSyncReadsOnFailure = false; }; struct LiteWalletRefreshPlan { bool ok = false; std::vector commands; std::string error; }; struct LiteWalletRefreshBundle { bool hasInfo = false; bool hasHeight = false; bool hasBalance = false; bool hasAddresses = false; bool hasNotes = false; bool hasTransactions = false; bool hasSyncStatus = false; bool complete = false; std::size_t successfulCommandCount = 0; LiteInfoResponse info; LiteHeightResponse height; LiteBalanceResponse balance; LiteAddressesResponse addresses; LiteNotesResponse notes; LiteTransactionsResponse transactions; LiteSyncStatusResponse syncStatus; }; struct LiteWalletRefreshResult { bool ok = false; bool attempted = false; bool cancelled = false; // keepGoing() returned false; partial results only bool syncReadFailed = false; // a server-bound command returned a backend error this cycle LiteWalletRefreshPlan plan; std::vector commandResults; LiteWalletRefreshBundle bundle; WalletBackendStatus status; std::string error; }; struct LiteWalletGatewayOptions { bool allowBridgeCalls = false; }; const char* liteWalletGatewayCommandName(LiteWalletGatewayCommand command); // Pure helpers (unit-tested). bool liteResponseIsBackendError(const std::string& response); // first non-space char is neither '{' nor '[' bool liteGatewayCommandReachesServer(LiteWalletGatewayCommand command); // Info/Balance/Notes/List; Height/Addresses are local int liteRefreshDelayMs(int consecutiveFailures, int baseMs); // base, x2 per failure, capped at 15000 ms const char* liteWalletGatewayAvailabilityName(LiteWalletGatewayAvailability availability); std::vector liteWalletRefreshCommands(const LiteWalletRefreshRequest& request); LiteWalletRefreshBundle assembleLiteWalletRefreshBundle(const std::vector& results, const LiteWalletRefreshRequest& request); class LiteWalletGateway { public: LiteWalletGateway(WalletCapabilities capabilities, LiteConnectionSettings connectionSettings, LiteClientBridge* bridge, LiteWalletGatewayOptions options = {}); const WalletCapabilities& capabilities() const { return capabilities_; } const LiteConnectionSettings& connectionSettings() const { return connectionSettings_; } const LiteWalletGatewayOptions& options() const { return options_; } LiteWalletGatewayAvailability availability() const; WalletBackendStatus status() const; LiteWalletGatewayPlan planCommand(const LiteWalletGatewayRequest& request) const; LiteWalletRefreshPlan planRefresh(const LiteWalletRefreshRequest& request) const; LiteWalletGatewayCommandResult fetchCommand(const LiteWalletGatewayRequest& request); LiteWalletRefreshResult refresh(const LiteWalletRefreshRequest& request); private: LiteServerSelectionResult selectServerForRequest(const std::string& serverUrl) const; WalletBackendStatus statusFor(LiteWalletGatewayAvailability availability, const std::string& detail = {}) const; LiteWalletGatewayCommandResult blockedCommandResult(const LiteWalletGatewayPlan& plan, const WalletBackendStatus& blockedStatus) const; LiteWalletGatewayCommandResult executePlannedCommand(const LiteWalletGatewayPlan& plan); LiteWalletGatewayCommandResult parseBridgeResponse(const LiteWalletGatewayPlan& plan, const std::string& response) const; WalletCapabilities capabilities_; LiteConnectionSettings connectionSettings_; LiteClientBridge* bridge_ = nullptr; // non-owning; owned by LiteWalletController LiteWalletGatewayOptions options_; }; } // namespace dragonx::wallet