Skip to content

Commit 652c4ac

Browse files
sbpublicclaude
andcommitted
feat(frontend): finalize signer toast copy (calmer, less technical)
unavailable: 'Signing is temporarily unavailable. Please try again shortly.' limit_reached: 'You've reached your signing limit. Please try again shortly.' Drops the chain list and the 'we're working on a fix' admission so the outage message reads neutrally (not like an incident on our side); the two now share a cadence and closing. Synced the quoted copy in spec + PRODUCT.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent d45785e commit 652c4ac

3 files changed

Lines changed: 15 additions & 15 deletions

File tree

docs/ai/PRODUCT.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ Every paid chain-fusion-signer call fires a `cfs_sign` Plausible event on **both
7777

7878
**User-facing behavior when signing can't be paid for.** When a signing call fails because the chain-fusion signer can't be paid (a `SignerCanisterPaymentError`), every affected flow — sending BTC/ETH/SOL, WalletConnect signing, and OpenCryptoPay payments — shows a calm message instead of the raw `Ledger error: …` text, distinguishing two cases:
7979

80-
- **Wallet-wide outage** (e.g. the backend is out of cycles): "we're temporarily unable to sign… working on a fix" (`sign.error.unavailable`).
81-
- **Per-user signing limit** (the caller's ICRC-2 allowance towards the signer is exhausted — `isSignerCanisterAllowanceError`, detected from a nested `InsufficientAllowance` in the ledger error): "you've reached your current signing limittry again later" (`sign.error.limit_reached`). In this case OISY also kicks off a best-effort background `allow_signing` re-grant (`replenishSignerAllowance`), so the next attempt can usually succeed without a page reload — unless the user has hit the `allow_signing` rate limit (the real per-user cap). The original operation is **not** auto-retried; the user retries it.
80+
- **Wallet-wide outage** (e.g. the backend is out of cycles): a neutral "Signing is temporarily unavailable. Please try again shortly." (`sign.error.unavailable`).
81+
- **Per-user signing limit** (the caller's ICRC-2 allowance towards the signer is exhausted — `isSignerCanisterAllowanceError`, detected from a nested `InsufficientAllowance` in the ledger error): "You've reached your signing limit. Please try again shortly." (`sign.error.limit_reached`). In this case OISY also kicks off a best-effort background `allow_signing` re-grant (`replenishSignerAllowance`), so the next attempt can usually succeed without a page reload — unless the user has hit the `allow_signing` rate limit (the real per-user cap). The original operation is **not** auto-retried; the user retries it.
8282

8383
This is centralised in the `toastsSignerUnavailableOr` helper (`toasts.store.ts`), which the catch sites route through; genuine user errors (invalid address, insufficient token balance, gas) keep their existing specific messages. Swap flows already surface a generic failure message and so were left unchanged.
8484

docs/ai/spec-driven-development/specs/2026-06-18-impr-cfs-signing-error-toast-and-cfs-sign-event.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@ Two related improvements triggered by a support incident:
88

99
1. **User-facing:** When the chain-fusion signer cannot sign because the OISY backend's
1010
account on the cycles ledger runs too low, users currently see a raw, scary toast.
11-
Replace it with a calm, generic message: we're temporarily unable to sign Bitcoin,
12-
Ethereum and Solana transactions and messages, we're aware of it, and a fix is coming.
13-
This affects **every** signing operation — sends, WalletConnect personal_sign / eth_sign,
14-
EIP-2612 permits, swaps — not just sends.
11+
Replace it with a calm, non-technical message that signing is temporarily unavailable and
12+
to try again shortly — without naming the affected chains, and without sounding like an
13+
incident on our side. This affects **every** signing operation — sends, WalletConnect
14+
personal_sign / eth_sign, EIP-2612 permits, swaps — not just sends.
1515

1616
While building this we realised the payment failure has **two distinct causes that must
1717
not share a message**:
18-
- **"Our fault" — backend out of cycles:** a wallet-wide outage we need to fix. Show the
19-
"we're working on a fix" message (`sign.error.unavailable`).
18+
- **"Our fault" — backend out of cycles:** a wallet-wide outage. Show the neutral
19+
"signing is temporarily unavailable" message (`sign.error.unavailable`).
2020
- **"As intended" — the user's signing allowance is exceeded:** a per-user limit working
21-
exactly as designed; nothing is broken on our side. Show a different, calmer
22-
"you've reached your limit, try again later" message (`sign.error.limit_reached`).
21+
exactly as designed; nothing is broken on our side. Show a distinct
22+
"you've reached your signing limit" message (`sign.error.limit_reached`).
2323

2424
2. **Observability:** Emit a `cfs_sign` Plausible event for **every paid chain-fusion-signer
2525
call** (success and error), carrying the called signer method and an appropriate
@@ -91,7 +91,7 @@ error leaks into the toast.
9191
- **per-user signing limit** — the caller's ICRC-2 allowance towards the signer is
9292
exhausted (surfaces as a nested `InsufficientAllowance` in the ledger transfer/withdraw
9393
error) → `sign.error.limit_reached`. _(PM decision: this is a per-user limit, not a global
94-
outage, so the "we're working on a fix" wording would be wrong.)_ The distinction is
94+
outage, so outage-style "it's on us, we're fixing it" wording would be wrong.)_ The distinction is
9595
**frontend-only** — the variant is already present in the signer's candid, so no
9696
chain-fusion-signer change is needed.
9797
- **Not send-specific:** the payment outage surfaces on every paid signer call, including
@@ -146,8 +146,8 @@ OISY-as-dApp-signer feature (`sign_in`, `permissions`, `consent_message`, …):
146146
```json
147147
"sign": {
148148
"error": {
149-
"unavailable": "We're temporarily unable to sign Bitcoin, Ethereum and Solana transactions and messages. We're aware of the issue and working on a fix. Please try again soon.",
150-
"limit_reached": "You've reached your current limit for signing transactions and messages. Please wait a little while and try again."
149+
"unavailable": "Signing is temporarily unavailable. Please try again shortly.",
150+
"limit_reached": "You've reached your signing limit. Please try again shortly."
151151
}
152152
}
153153
```

src/frontend/src/lib/i18n/en.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,8 +1931,8 @@
19311931
},
19321932
"sign": {
19331933
"error": {
1934-
"unavailable": "We're temporarily unable to sign Bitcoin, Ethereum and Solana transactions and messages. We're aware of the issue and working on a fix. Please try again soon.",
1935-
"limit_reached": "You've reached your current limit for signing transactions and messages. Please wait a little while and try again."
1934+
"unavailable": "Signing is temporarily unavailable. Please try again shortly.",
1935+
"limit_reached": "You've reached your signing limit. Please try again shortly."
19361936
}
19371937
},
19381938
"signer": {

0 commit comments

Comments
 (0)