fix(lite): gateway refresh degrades gracefully on a failed command
LiteWalletGateway::refresh() aborted the entire refresh on the first command whose bridge call or parse failed — which turned a single real-backend shape mismatch (e.g. syncstatus) into a total, empty-everything refresh. Since the balance/addresses/list real shapes are still unverified and we've already hit shape drift twice, make refresh resilient: - Run every planned command; assembleLiteWalletRefreshBundle already skips failed results. - result.ok = any usable data came back (bundle.complete still reflects all-succeeded). - One command's failure now degrades gracefully — the other sections still populate. testLiteWalletGatewayRefreshSkipsFailedCommand (fake balance returns invalid JSON) asserts the refresh still succeeds with addresses/transactions/info populated and balance skipped. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -230,24 +230,33 @@ LiteWalletRefreshResult LiteWalletGateway::refresh(const LiteWalletRefreshReques
|
||||
}
|
||||
|
||||
result.attempted = true;
|
||||
// Run every planned command. A single command's bridge or parse failure must NOT abort the
|
||||
// whole refresh — partial data beats none, and real-backend response shapes can drift per
|
||||
// command. assembleLiteWalletRefreshBundle() ignores the failed results.
|
||||
for (const auto& commandPlan : result.plan.commands) {
|
||||
auto commandResult = executePlannedCommand(commandPlan);
|
||||
if (!commandResult.ok) {
|
||||
result.status = commandResult.status;
|
||||
result.error = commandResult.error;
|
||||
result.commandResults.push_back(std::move(commandResult));
|
||||
return result;
|
||||
}
|
||||
result.commandResults.push_back(std::move(commandResult));
|
||||
result.commandResults.push_back(executePlannedCommand(commandPlan));
|
||||
}
|
||||
|
||||
result.bundle = assembleLiteWalletRefreshBundle(result.commandResults, request);
|
||||
result.ok = result.bundle.complete;
|
||||
result.status = refreshStatusForRequest(request);
|
||||
|
||||
// Succeed if anything usable came back; some commands may have been skipped. (bundle.complete
|
||||
// still reflects whether *all* commands succeeded, for callers that care.)
|
||||
result.ok = result.bundle.successfulCommandCount > 0 || result.bundle.hasSyncStatus;
|
||||
if (!result.ok) {
|
||||
result.status = makeGatewayStatus(WalletBackendState::Error, "lite refresh bundle is incomplete");
|
||||
result.error = result.status.message;
|
||||
for (const auto& commandResult : result.commandResults) {
|
||||
if (!commandResult.ok) {
|
||||
result.status = commandResult.status;
|
||||
result.error = commandResult.error;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result.error.empty()) {
|
||||
result.status = makeGatewayStatus(WalletBackendState::Error, "lite refresh produced no usable data");
|
||||
result.error = result.status.message;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
result.status = refreshStatusForRequest(request);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user