classifyShieldSendFailure function

ShieldState classifyShieldSendFailure(
  1. Object error
)

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());
}