feat(lite): M2b-3 — background refresh worker + App::update hook
- LiteWalletController owns a background std::thread worker that, once a wallet is ready,
refreshes every ~4s and publishes a copyable LiteWalletAppRefreshModel under a mutex.
Worker auto-starts on lifecycle-ready and is stopped+joined in the destructor. status_
is written only on the main thread; walletOpen_/syncStarted_ are atomic.
- App::update() calls takeRefreshedModel() and applies it into state_ on the main thread
(WalletState is non-copyable, so the model crosses the thread boundary, not the state),
so the existing Balance/Receive/Transactions tabs populate from lite data.
- refreshWalletState() refactored onto refreshModel() (pure, worker-safe).
- testLiteWalletControllerWorkerProducesModel verifies the worker publishes a populated
model (stable across repeated runs). Builds clean in all configs.
Real-backend smoke (lite_smoke --refresh now runs real output through the parsers) found
two integration bugs, documented in the plan for follow-up:
- syncstatus parser requires synced_blocks/total_blocks but the real idle response is
{"syncing":"false"} (string), so it fails to parse when not actively syncing.
- the first data query (balance/list) blocks on a full chain sync, which would hang the
worker's shutdown join — needs a cancel/timeout path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "wallet/lite_client_bridge.h"
|
||||
#include "wallet/lite_connection_service.h"
|
||||
#include "wallet/lite_result_parsers.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
@@ -22,12 +23,17 @@
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
using namespace dragonx::wallet;
|
||||
std::setvbuf(stdout, nullptr, _IONBF, 0); // unbuffered so output survives a timeout kill
|
||||
|
||||
std::string server = "https://lite.dragonx.is";
|
||||
bool doCreate = false;
|
||||
bool doRefresh = false;
|
||||
bool doFull = false;
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
const std::string arg = argv[i];
|
||||
if (arg == "--create") doCreate = true;
|
||||
else if (arg == "--refresh") doRefresh = true;
|
||||
else if (arg == "--full") doFull = true;
|
||||
else server = arg;
|
||||
}
|
||||
|
||||
@@ -61,6 +67,49 @@ int main(int argc, char** argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (doRefresh) {
|
||||
// Run each refresh command through the real parser to verify the LIVE backend's
|
||||
// JSON shapes match what the gateway expects. Prints flags/counts only (no secrets,
|
||||
// addresses, or amounts).
|
||||
std::printf("[lite-smoke] --- refresh shape check (real backend output -> parsers) ---\n");
|
||||
{
|
||||
auto r = bridge.execute("info", "");
|
||||
auto p = parseLiteInfoResponse(r.value);
|
||||
std::printf("[lite-smoke] info bridge_ok=%d parse_ok=%d err=%s\n",
|
||||
r.ok, p.ok, liteResultParserErrorName(p.error));
|
||||
}
|
||||
{
|
||||
auto r = bridge.execute("syncstatus", "");
|
||||
auto p = parseLiteSyncStatusResponse(r.value);
|
||||
std::printf("[lite-smoke] syncstatus bridge_ok=%d parse_ok=%d err=%s synced=%llu/%llu\n",
|
||||
r.ok, p.ok, liteResultParserErrorName(p.error),
|
||||
(unsigned long long)p.syncStatus.syncedBlocks, (unsigned long long)p.syncStatus.totalBlocks);
|
||||
std::printf("[lite-smoke] syncstatus RAW = %.200s\n", r.value.c_str());
|
||||
}
|
||||
// The data commands below trigger a blocking full-chain sync on a fresh wallet;
|
||||
// gate them behind --full so the shape check stays fast by default.
|
||||
if (!doFull) { bridge.shutdown(); std::printf("[lite-smoke] (skipping balance/addresses/list; pass --full)\n"); return 0; }
|
||||
{
|
||||
auto r = bridge.execute("balance", "");
|
||||
auto p = parseLiteBalanceResponse(r.value);
|
||||
std::printf("[lite-smoke] balance bridge_ok=%d parse_ok=%d err=%s\n",
|
||||
r.ok, p.ok, liteResultParserErrorName(p.error));
|
||||
}
|
||||
{
|
||||
auto r = bridge.execute("addresses", "");
|
||||
auto p = parseLiteAddressesResponse(r.value);
|
||||
std::printf("[lite-smoke] addresses bridge_ok=%d parse_ok=%d err=%s z=%zu t=%zu\n",
|
||||
r.ok, p.ok, liteResultParserErrorName(p.error),
|
||||
p.addresses.zAddresses.size(), p.addresses.tAddresses.size());
|
||||
}
|
||||
{
|
||||
auto r = bridge.execute("list", "");
|
||||
auto p = parseLiteTransactionsResponse(r.value);
|
||||
std::printf("[lite-smoke] list bridge_ok=%d parse_ok=%d err=%s count=%zu\n",
|
||||
r.ok, p.ok, liteResultParserErrorName(p.error), p.transactions.transactions.size());
|
||||
}
|
||||
}
|
||||
|
||||
bridge.shutdown();
|
||||
std::printf("[lite-smoke] done (real litelib_* symbols are callable; results above are live)\n");
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user