fix(lite): parse real syncstatus shapes (idle vs in-progress)

The real backend returns syncstatus as idle {"syncing":"false"} (string) or in-progress
{"syncing":"true","synced_blocks":N,"total_blocks":M} (commands.rs:83-87), but
parseLiteSyncStatusResponse hard-required the block fields and failed whenever the wallet
wasn't actively syncing — so sync/progress never updated in the real app.

- Read "syncing" as a string; require synced_blocks/total_blocks only when syncing=true;
  idle => complete, synced/total 0.
- fake_lite_backend syncstatus now uses the real "syncing":"true" shape.
- testLiteSyncStatusParserRealShapes covers idle, in-progress, and missing-counts-while-syncing.
- Verified against the live backend via lite_smoke --refresh (syncstatus parse_ok=1).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-04 22:52:42 -05:00
parent a8b5d2f6a3
commit 59c55e33f8
4 changed files with 55 additions and 8 deletions

View File

@@ -557,11 +557,27 @@ LiteSyncStatusParseResult parseLiteSyncStatusResponse(const json& value)
{
auto result = makeResult<LiteSyncStatusParseResult>(LiteResultCommand::SyncStatus);
if (!requireObject(value, "$", result)) return result;
if (!readRequiredUnsignedField(value, "synced_blocks", result.syncStatus.syncedBlocks, result)) return result;
if (!readRequiredUnsignedField(value, "total_blocks", result.syncStatus.totalBlocks, result)) return result;
if (result.syncStatus.totalBlocks > 0) {
result.syncStatus.progress = std::min(1.0, static_cast<double>(result.syncStatus.syncedBlocks) / static_cast<double>(result.syncStatus.totalBlocks));
result.syncStatus.complete = result.syncStatus.syncedBlocks >= result.syncStatus.totalBlocks;
// The backend reports "syncing" as a STRING ("true"/"false"). synced_blocks/total_blocks
// are present only while actively syncing; an idle wallet returns just {"syncing":"false"}.
std::string syncing = "false";
if (!readOptionalStringField(value, "syncing", syncing, result)) return result;
const bool isSyncing = (syncing == "true" || syncing == "1");
if (isSyncing) {
if (!readRequiredUnsignedField(value, "synced_blocks", result.syncStatus.syncedBlocks, result)) return result;
if (!readRequiredUnsignedField(value, "total_blocks", result.syncStatus.totalBlocks, result)) return result;
result.syncStatus.complete = false; // actively syncing
result.syncStatus.progress = result.syncStatus.totalBlocks > 0
? std::min(1.0, static_cast<double>(result.syncStatus.syncedBlocks) /
static_cast<double>(result.syncStatus.totalBlocks))
: 0.0;
} else {
// Not actively syncing: the backend reports no block counts. Treat as idle/caught-up.
result.syncStatus.syncedBlocks = 0;
result.syncStatus.totalBlocks = 0;
result.syncStatus.complete = true;
result.syncStatus.progress = 1.0;
}
succeed(result);
return result;