Skip to content

fix(deposits): stop support-chat clicks from cancelling deposits + confirm-before-cancel + uniform reference#2416

Merged
jjramirezn merged 3 commits into
mainfrom
fix/deposit-cancel-confirmation
Jul 14, 2026
Merged

fix(deposits): stop support-chat clicks from cancelling deposits + confirm-before-cancel + uniform reference#2416
jjramirezn merged 3 commits into
mainfrom
fix/deposit-cancel-confirmation

Conversation

@abalinda

@abalinda abalinda commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

The bug, explained for a stupid 5-year-old 🖍️

The transaction screen has two buttons near each other:

  • 🟢 "Issues with this transaction?" — calls support for help. Totally harmless.
  • 🔴 "Cancel deposit" — shreds your deposit order. Forever.

You press the green button and a big support-chat window slides up in front of everything. Looks great. Except the chat window is a hologram: the page underneath had told the browser "ignore fingers" (that's what the transaction drawer does while it's open), and the chat window forgot to say "except me — fingers stop HERE!". So it looks solid, but your finger goes straight through the glass.

Now you tap the chat to type your message… and the browser delivers that tap to whatever is behind the hologram at that exact spot. And what's behind it, right there? The red shred button. Click. Deposit cancelled. You never saw it, you never meant it, and the money that arrives at the bank can no longer be matched to anything.

That's why the fix is not "disconnect the green button from cancel" — there was never a wire between them. The green button was innocent. The fix is two words, pointer-events-auto: "this glass is solid." Plus a seatbelt: the shred button now always asks "are you REALLY sure?" — so no stray tap can ever shred money in one touch again.


Replaces #2415 (closed — wrong diagnosis). Three fixes, grounded in the Valentin case (Crisp session_27a67f97) and reproduced by @abalinda (intent cbc0fd7d-14e9-4a6c-b5be-c54dbe0c49ee):

  1. ROOT CAUSE — "Issues with this transaction?" cancelled deposits via click fall-through. vaul sets pointer-events: none on <body> while the transaction drawer is open; the SupportDrawer's backdrop and panel never re-enabled pointer events, so the entire support overlay inherited none and was click-transparent. Taps on the visually-open support chat fell through to the receipt underneath — where Cancel deposit renders adjacent to the support link — and fired the un-guarded cancel. PostHog element chains prove it: support link clicked 15:05:47.742 → fall-through click autocaptured on Cancel deposit 15:05:48.798 (1.06s — not a human aim) → BE user_cancelled 15:05:49.444, with body[style="pointer-events: none"] captured in both chains. Fixed with explicit pointer-events-auto on the backdrop and panel while open, plus a regression test.

  2. Confirmation before any deposit/request cancel (defense in depth — the cancel is irreversible money-state). All three cancel variants (Bridge onramp, Manteca onramp, bank request) now arm a shared ActionModal confirmation warning that a sent transfer can no longer be matched after cancelling. Even a fall-through click can now only open the modal, never cancel.

  3. Uniform 10-char deposit reference. The Add Money screen intentionally shortens the Bridge reference to 10 chars (some banks, e.g. Wise, cap reference fields; Bridge matches deposits on the partial reference) — but the transaction drawer showed the full 20-char form. Seeing 'two different codes' is what sent the user into the drawer in a panic in the first place. Both screens now route through a single shortDepositReference() helper (6 call sites), so the lengths can't drift apart again.

Before (drawer 20 char; deposit flow transaction screen 10 chars)

image image

Now - 10 chars everywhere + cancel confirmation popup + "Need help with this transaction" doesn't trigger auto-cancel

image image

this is after clicking on the explicit "Cancel deposit"
image

Design notes / accepted trade-offs

  • Confirmation modal lives inside CancelDepositActions reusing the global ActionModal (same pattern as CancelSendLinkModal) — one modal serves all three cancel branches, parameterized by noun (deposit/request).
  • The drawer truncation is display+copy — uniform with Add Money. The full reference is no longer shown anywhere in the UI (deliberate, per product decision — Bridge matches on the partial). If support ever needs the full form for manual reconciliation, it stays available in the DB/Bridge dashboard; surfacing it in-app would be a follow-up, not a mismatch.
  • The z-[9999]/pointer-events modal-stacking overrides are the third copy of this pattern (CancelSendLinkModal, TokenAndNetworkConfirmationModal) — extracting a shared confirm-in-drawer wrapper is a follow-up, out of hotfix scope.

Risks / breaking changes

  • None cross-repo; FE-only. Cancel behaviour unchanged after confirmation.
  • Hotfix to main → back-merge debt main→dev after merge.

QA

  • New suites: CancelDepositActions.test.tsx (3 tests: click ≠ cancel, confirm → cancel, dismiss → untouched), BridgeDepositInstructions.test.tsx (shortened ref in display + copy), and a SupportDrawer regression test asserting backdrop + panel carry pointer-events-auto while open (the vaul-inheritance trap).
  • Full local gate: prettier ✅ · typecheck ✅ · jest 1832 tests ✅ · changed-files eslint clean.
  • Visual QA: local harness, pending bank deposit → drawer → Cancel deposit shows confirmation; reference matches Add Money screen; support chat opens and absorbs clicks.

A user cancelled a funded bank deposit while trying to report a problem:
the cancel button sits next to the support link and fired instantly with
no confirmation (PostHog: 'Issues with this transaction?' at 09:03:00,
'Cancel deposit' 11s later), making the arriving wire unmatchable.

The drawer also showed the FULL deposit reference while Add Money shows
the intentionally shortened 10-char form (some banks cap reference
fields; Bridge matches on the partial) — the two-different-codes
confusion that sent the user hunting in the drawer to begin with.
@vercel

vercel Bot commented Jul 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
peanut-wallet Ready Ready Preview, Comment Jul 14, 2026 4:20pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@abalinda, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 40 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: da5e31c5-2836-41ac-bf29-8cb4e670b1bc

📥 Commits

Reviewing files that changed from the base of the PR and between 6347c3b and 3e1f71e.

📒 Files selected for processing (2)
  • src/components/TransactionDetails/provider-actions/CancelDepositActions.tsx
  • src/components/TransactionDetails/provider-actions/__tests__/CancelDepositActions.test.tsx

Walkthrough

Changes

The PR standardizes deposit-reference shortening, adds confirmation before deposit or request cancellation, and explicitly manages SupportDrawer pointer events during open and closed states.

Deposit reference formatting

Layer / File(s) Summary
Shortened deposit reference integration
src/utils/format.utils.ts, src/components/AddMoney/..., src/components/TransactionDetails/provider-rows/...
Adds shortDepositReference and applies it to deposit-reference display, copying, sharing, and warning text, with tests covering shortened output.

Cancellation confirmation

Layer / File(s) Summary
Cancellation confirmation flow
src/components/TransactionDetails/provider-actions/...
Stores pending cancellation actions, presents an ActionModal, and executes cancellation only after confirmation; tests cover confirmation and dismissal.

SupportDrawer pointer events

Layer / File(s) Summary
SupportDrawer pointer-event toggling
src/components/Global/SupportDrawer/...
Adds explicit open-state pointer-events-auto classes for the backdrop and panel and verifies the behavior in tests.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: hugo0

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately summarizes the main changes: fixing support-click fall-through, adding cancel confirmation, and unifying deposit references.
Description check ✅ Passed The description is clearly related to the changeset and explains the support overlay fix, cancel confirmation, and shortened reference updates.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@abalinda

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 6109.87 → 6111.31 (+1.44)
Findings: 0 net (+13 new, -13 resolved)

🆕 New findings (13)

  • critical complexity — src/components/AddMoney/components/AddMoneyBankDetails.tsx — CC 83, MI 58.18, SLOC 152
  • high method-complexity — src/components/AddMoney/components/AddMoneyBankDetails.tsx:50 — AddMoneyBankDetails CC 33 SLOC 66
  • high complexity — src/components/TransactionDetails/provider-actions/CancelDepositActions.tsx — CC 33, MI 64.65, SLOC 108
  • medium high-mdd — src/components/TransactionDetails/provider-rows/BridgeDepositInstructions.tsx:24 — BridgeDepositInstructions: MDD 106.8 (uses across many lines from declarations)
  • medium high-mdd — src/components/Global/SupportDrawer/index.tsx:15 — SupportDrawer: MDD 46.2 (uses across many lines from declarations)
  • medium high-mdd — src/components/TransactionDetails/provider-actions/CancelDepositActions.tsx:29 — CancelDepositActions: MDD 26.4 (uses across many lines from declarations)
  • medium method-complexity — src/components/AddMoney/components/AddMoneyBankDetails.tsx:179 — CC 22 SLOC 23
  • medium complexity — src/components/TransactionDetails/provider-rows/BridgeDepositInstructions.tsx — CC 17, MI 65.37, SLOC 15
  • medium complexity — src/utils/format.utils.ts — CC 17, MI 62.06, SLOC 62
  • medium method-complexity — src/components/TransactionDetails/provider-rows/BridgeDepositInstructions.tsx:24 — BridgeDepositInstructions CC 15 SLOC 11
  • low high-dlt — src/components/TransactionDetails/provider-actions/CancelDepositActions.tsx:29 — CancelDepositActions: DLT 21 (calls 21 distinct functions — high context load)
  • low missing-return-type — src/components/TransactionDetails/provider-actions/CancelDepositActions.tsx:29 — CancelDepositActions: exported fn missing return type annotation
  • low missing-return-type — src/components/TransactionDetails/provider-rows/BridgeDepositInstructions.tsx:24 — BridgeDepositInstructions: exported fn missing return type annotation

✅ Resolved (13)

  • src/components/AddMoney/components/AddMoneyBankDetails.tsx — CC 83, MI 58.4, SLOC 148
  • src/components/AddMoney/components/AddMoneyBankDetails.tsx:50 — AddMoneyBankDetails CC 33 SLOC 63
  • src/components/TransactionDetails/provider-rows/BridgeDepositInstructions.tsx:23 — BridgeDepositInstructions: MDD 105.0 (uses across many lines from declarations)
  • src/components/Global/SupportDrawer/index.tsx:15 — SupportDrawer: MDD 44.8 (uses across many lines from declarations)
  • src/components/TransactionDetails/provider-actions/CancelDepositActions.tsx — CC 28, MI 66.56, SLOC 79
  • src/components/AddMoney/components/AddMoneyBankDetails.tsx:179 — CC 22 SLOC 22
  • src/components/TransactionDetails/provider-rows/BridgeDepositInstructions.tsx — CC 17, MI 66.76, SLOC 13
  • src/utils/format.utils.ts — CC 16, MI 60.76, SLOC 60
  • src/components/TransactionDetails/provider-rows/BridgeDepositInstructions.tsx:23 — BridgeDepositInstructions CC 15 SLOC 9
  • src/components/TransactionDetails/provider-actions/CancelDepositActions.tsx:28 — CancelDepositActions: MDD 17.1 (uses across many lines from declarations)
  • src/components/TransactionDetails/provider-actions/CancelDepositActions.tsx:28 — CancelDepositActions: DLT 17 (calls 17 distinct functions — high context load)
  • src/components/TransactionDetails/provider-actions/CancelDepositActions.tsx:28 — CancelDepositActions: exported fn missing return type annotation
  • src/components/TransactionDetails/provider-rows/BridgeDepositInstructions.tsx:23 — BridgeDepositInstructions: exported fn missing return type annotation

📈 Painscore deltas (top movers)

File Before After Δ
src/components/TransactionDetails/provider-actions/CancelDepositActions.tsx 7.1 7.9 +0.8
src/components/TransactionDetails/provider-rows/BridgeDepositInstructions.tsx 11.2 11.9 +0.7

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • unit: 1836 ran, 0 failed, 0 skipped, 28.2s

📊 Coverage (unit)

metric %
statements 58.2%
branches 42.2%
functions 47.0%
lines 58.3%
⏱ 10 slowest test cases
time test
3.4s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › never places two stickers in heavy overlap (broad seed sweep)
0.4s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › every sticker stays within canvas at any count
0.3s src/app/actions/__tests__/api-headers.test.ts › should include Content-Type in updateUserById
0.3s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › keeps stickers off the username pill (final pass respects the keep-out)
0.3s src/app/actions/__tests__/api-headers-extended.test.ts › should not include apiKey in updateUserById body
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle valid 9-digit US account
0.1s src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx › Manteca PIX form ready shows merchant card + amount input + pay button
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle valid ETH address
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle invalid ETH address (missing 0x prefix)
0.1s src/components/Global/GeneralRecipientInput/__tests__/GeneralRecipientInput.test.tsx › should handle minimum length (6 digits) US account
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

…a vaul drawer

Root cause of the phantom deposit cancels: vaul sets pointer-events:none
on body while the transaction drawer is open, and the SupportDrawer's
backdrop/panel never re-enabled pointer events — the whole support
overlay was click-transparent, so taps on it fell through to the receipt
underneath, where 'Cancel deposit' sits adjacent to the support link and
fired irreversibly (PostHog: support link 15:05:47.7 → fall-through
click on Cancel deposit 15:05:48.8 → BE cancel 15:05:49.4).

Also per code review: single shortDepositReference() helper for the
6 reference sites across both screens, separate confirm-modal visibility
from the armed action (noun flashed mid-fade), drop no-op icon props.
@abalinda abalinda changed the title fix(deposits): confirm before cancelling + uniform shortened deposit reference fix(deposits): stop support-chat clicks from cancelling deposits + confirm-before-cancel + uniform reference Jul 14, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/components/Global/SupportDrawer/__tests__/SupportDrawer.test.tsx (1)

159-174: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Exercise the Vaul regression state in this test.

This only checks class strings while the drawer is open; it never simulates Vaul’s document.body.style.pointerEvents = 'none' state or verifies that closed elements retain pointer-events-none. Add assertions for both open and closed states, ideally with the body pointer-events condition set before rendering.

🤖 Prompt for 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.

In `@src/components/Global/SupportDrawer/__tests__/SupportDrawer.test.tsx` around
lines 159 - 174, Update the SupportDrawer test to set
document.body.style.pointerEvents to none before rendering, then assert the open
backdrop and panel explicitly use pointer-events-auto. Also exercise the closed
state and verify the relevant elements retain pointer-events-none, covering both
Vaul’s regression condition and normal closed behavior.
src/components/TransactionDetails/provider-actions/CancelDepositActions.tsx (1)

70-70: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Synchronize the error message with the cancelled item.

Since this PR introduces dynamic terminology (noun) for requests vs. deposits, you can use it here to ensure the error text matches the user's intended action instead of hardcoding "deposit".

✨ Proposed adjustment
-            setError("We couldn't cancel this deposit. Please try again or contact support.")
+            setError(`We couldn't cancel this ${pendingCancel?.noun ?? 'deposit'}. Please try again or contact support.`)
🤖 Prompt for 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.

In `@src/components/TransactionDetails/provider-actions/CancelDepositActions.tsx`
at line 70, Update the error message in the cancel action to use the existing
dynamic noun terminology instead of hardcoding “deposit,” ensuring the text
matches whether the cancelled item is a request or deposit. Preserve the current
retry and support guidance.
🤖 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/TransactionDetails/provider-actions/CancelDepositActions.tsx`:
- Line 47: Update the pendingCancel state type and confirmThenRun flow to allow
an absent run action. In confirmThenRun, capture the current action, immediately
clear run while preserving noun, then execute the captured action only once so
repeated confirmation taps cannot start concurrent cancellations.

---

Nitpick comments:
In `@src/components/Global/SupportDrawer/__tests__/SupportDrawer.test.tsx`:
- Around line 159-174: Update the SupportDrawer test to set
document.body.style.pointerEvents to none before rendering, then assert the open
backdrop and panel explicitly use pointer-events-auto. Also exercise the closed
state and verify the relevant elements retain pointer-events-none, covering both
Vaul’s regression condition and normal closed behavior.

In `@src/components/TransactionDetails/provider-actions/CancelDepositActions.tsx`:
- Line 70: Update the error message in the cancel action to use the existing
dynamic noun terminology instead of hardcoding “deposit,” ensuring the text
matches whether the cancelled item is a request or deposit. Preserve the current
retry and support guidance.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ad421249-6980-41e0-899d-faba29946e97

📥 Commits

Reviewing files that changed from the base of the PR and between a5cc747 and 6347c3b.

📒 Files selected for processing (8)
  • src/components/AddMoney/components/AddMoneyBankDetails.tsx
  • src/components/Global/SupportDrawer/__tests__/SupportDrawer.test.tsx
  • src/components/Global/SupportDrawer/index.tsx
  • src/components/TransactionDetails/provider-actions/CancelDepositActions.tsx
  • src/components/TransactionDetails/provider-actions/__tests__/CancelDepositActions.test.tsx
  • src/components/TransactionDetails/provider-rows/BridgeDepositInstructions.tsx
  • src/components/TransactionDetails/provider-rows/__tests__/BridgeDepositInstructions.test.tsx
  • src/utils/format.utils.ts

… twice

CodeRabbit finding: two taps during the modal fade both see the armed
action and start concurrent cancellations. Ref guard, not state — a
same-frame double-tap lands before any re-render.
@abalinda abalinda marked this pull request as ready for review July 14, 2026 16:24
@jjramirezn jjramirezn merged commit 9b4f6f2 into main Jul 14, 2026
24 of 26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants