classifyShieldSendFailure function
Map a shield send (sign+broadcast) failure to the next ShieldState. A
consumed token is the honest "already submitted" (the notes are never
broadcast twice, §6.3); a stale anchor routes to re-prepare; everything else
is a no-money-moved sign failure. Reads kind only (§5.4) — mirrors the send
flow's classifySendFailure, projected onto the shield states.
Implementation
ShieldState classifyShieldSendFailure(Object error) {
if (error is WalletApiError) {
return switch (error.kind) {
WalletErrorKind_ProposalAlreadyUsed() => const ShieldDone(
SendAlreadySubmitted(),
),
WalletErrorKind_ProposalStale() => const ShieldUnavailable(
ShieldFaultReason.notSyncedYet,
),
// storeBusy joins this arm for parity with the send flow (#373): a shield
// write that lost its race to a sync commit (past the SDK's bounded retry)
// wrote nothing — the honest "busy, try again in a moment", never a
// generic "couldn't prepare" / "sign failed" dead-end.
WalletErrorKind_WalletBusy() ||
WalletErrorKind_InvalidState() ||
WalletErrorKind_StoreBusy() => const ShieldUnavailable(
ShieldFaultReason.walletBusy,
),
// Out of disk persisting the shield tx (#373 follow-up): nothing broadcast
// (§6.3), so route to the honest "free up space" retryable state, never the
// terminal "couldn't shield" dead-end that would loop on a full disk.
WalletErrorKind_DiskFull() => const ShieldUnavailable(
ShieldFaultReason.storageFull,
),
_ => const ShieldDone(SendSignFailed()),
};
}
return const ShieldDone(SendSignFailed());
}