classifyShieldPrepareFailure function
Map a proposeShield failure to a ShieldState. Reads the typed
WalletApiError.kind ONLY (never a payload โ ยง5.4); a non-FRB error is the
generic ShieldFaultReason.couldNotPrepare. Pure + total, unit-tested at its
boundary without a device.
Implementation
ShieldState classifyShieldPrepareFailure(Object error) {
if (error is WalletApiError) {
return switch (error.kind) {
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 (#373 follow-up): the honest "free up space", never a generic
// "couldn't prepare" that retries into a deterministic re-fail on a full disk.
WalletErrorKind_DiskFull() => const ShieldUnavailable(
ShieldFaultReason.storageFull,
),
// INC-018 (b), phase-2 P2-2 (the Batch C arch pass): the retryable class
// the SDK types apart reaches Shield as it reaches Send โ its OWN arm, so
// the sheet says "try again in a moment" and never the title-only
// dead-end the wildcard renders.
WalletErrorKind_ProposeTransient() => const ShieldUnavailable(
ShieldFaultReason.couldNotPrepareTransient,
),
_ => const ShieldUnavailable(ShieldFaultReason.couldNotPrepare),
};
}
return const ShieldUnavailable(ShieldFaultReason.couldNotPrepare);
}