fix(send-link): keep submit-time errors visible through balance polls#2513
Conversation
The balance-gate effect shares one errorState slot with submit-time failures (Rain signature-cooldown 425, settling copy). Right after a collateral spend the ~30s-polled spendable balance oscillates around the typed amount, so the gate overwrote the submit error with the insufficient-balance copy on the dip and then cleared it on the recovery - the user's real error silently vanished while they still couldn't spend (PostHog session 019f8f8c-d4d5-775c-97ab-3e47c532a694). The gate now only claims the error slot when it is free or already showing its own message; submit-time errors persist until the user retries or edits.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthrough
ChangesLink send error ownership
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Code-analysis diffPainscore total: 6267.93 → 6268.09 (+0.16) 🆕 New findings (3)
✅ Resolved (3)
|
🧪 UI test report — ✅ all greenSuites
📊 Coverage (unit)
⏱ 10 slowest test cases
|
…ched view New code must lint clean: type the Button mock and drop the any-spread in the useWallet mock. The touched view's '@/context' barrel import is swapped for the specific loadingStates.context file (same module instance, restricted-imports rule).
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/components/Send/link/views/Initial.link.send.view.tsx`:
- Around line 153-161: Complete error ownership in the balance polling and
amount editing flow: update the balance === undefined branch so it clears the
balance value without clearing an existing error, and replace the direct
AmountInput setTokenValue callback with a handler that clears the active error
before updating the amount. Add regressions covering both transitions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: bd7b1704-db03-414a-9e1b-1ebabc8fc472
📒 Files selected for processing (2)
src/components/Send/link/views/Initial.link.send.view.tsxsrc/components/Send/link/views/__tests__/Initial.link.send.view.test.tsx
Two more transitions could still eat a submit-time error: a momentarily-unavailable balance cleared every error (now releases only the gate's own message; an emptied amount still clears all - that IS user input), and editing the amount left a stale failure on screen (now released back to the gate, which re-flags a genuine shortfall on the new amount). Regression tests for both.
Summary
QA repro: "Error message when creating sendlink disappears (found with signature cooldown)."
The send-link balance-gate
useEffectand submit-time failures (Rain withdrawal-signature cooldown 425, balance-settling copy, passkey errors) share oneerrorStateslot. Right after a collateral spend the ~30s-polled spendable balance oscillates around the typed amount, so the gate overwrote the submit-time error withINSUFFICIENT_BALANCE_MESSAGEon the dip, and its recovery branch then cleared that swapped-in message — the real error silently vanished while the user still couldn't spend for ~2 min. The 2026-06-24 guard (#4661a2b) protected the clear side but not the overwrite side.Fix — a complete ownership model for the shared error slot:
Evidence: PostHog session
019f8f8c-d4d5-775c-97ab-3e47c532a694(2026-07-23 15:18) — $100 mixed-strategy link armed the signature lock, $20 retry hit the cooldown 425, error shown then swallowed; funds were oscillating right at the $20 boundary (twoinsufficientroutings seconds earlier prove it).Design notes / accepted trade-offs
INSUFFICIENT_BALANCE_MESSAGE= gate-owned). A source-tagged error state (source: 'gate' | 'submit') would be more durable if a third owner ever appears — noted as a possible follow-up, not needed for two owners.@/contextbarrel import → specificloadingStates.contextfile (same module instance; clears ano-restricted-importserror).Risks / breaking changes
None cross-repo. FE-only, narrow behavior change in when an already-existing error string is shown/cleared. Gate-owned insufficient-balance errors keep their appear/clear behavior (covered by test).
QA
npm test -- --testPathPattern Initial.link.send.view— 4-test regression suite; the original repro test verified failing ondevwithout the fix.Screenshots
N/A — no visual change; the fix keeps the existing
ErrorAlertmounted (copy: "A previous withdrawal signature is still active. Try again in about 2 min.") instead of it disappearing.