Skip to content

fix(send): keep the send framing past the amount step - #2625

Merged
abalinda merged 4 commits into
devfrom
fix/send-flow-withdraw-copy
Aug 6, 2026
Merged

fix(send): keep the send framing past the amount step#2625
abalinda merged 4 commits into
devfrom
fix/send-flow-withdraw-copy

Conversation

@abalinda

@abalinda abalinda commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Pick Send → Exchange or Wallet, enter an amount, and the next screen says "You're withdrawing".

Send has no destination screens of its own — SendRouter navigates into the withdraw routes:

case 'exchange-or-wallet': router.push('/withdraw?method=crypto')
case 'bank':               router.push('/withdraw?method=bank')

?method= is therefore the only signal that the user framed this as a send. /withdraw honours it (NavHeader "Send", "Amount to send") and forwards it to /withdraw/crypto?method=crypto — but that page never called useSearchParams(). The marker arrived and was dropped, so every screen after the amount step reverted to withdraw copy. That's what makes it jarring: the screen before says Send, the screen after says Withdrawing.

Why this isn't a one-word fix

PeanutActionDetailsCard maps one transactionType to one title, and WITHDRAW is genuinely both a withdrawal and a send depending on how the user arrived. So the line has already been flipped in opposite directions twice:

Commit Author Date Change
abd71b882 kushagrasarathe 2026-03-20 "you're withdrawing" → "you're sending"
d532b6a65 0xkkonrad 2026-07-13 "You're sending" → "You're withdrawing"

d532b6a65 names the seam exactly — "the frame is named by user intent while the card was named by the underlying mechanism" — and then picks a side. Both engineers were right about the flow in front of them. Flipping it a third time would re-break the real withdraw flow and get flipped again. This PR adds the discriminator that was missing instead.

Design notes / accepted trade-offs

  • isFromSendFlow is a presentation flag, not a new transactionType. The transaction really is a withdraw; only the verb differs. A new union member would have forced matching edits in getIcon / getAvatarIcon / getAvatarBackgroundColor / getAvatarTextColor purely to reproduce identical visuals — arrow-up and wallet-outline are already right for both framings. One ternary also covers WITHDRAW_BANK_ACCOUNT, which is why the bank path came nearly free.
  • PaymentSuccessView keeps isWithdrawFlow={true}. Tempting to flip it, but it also suppresses the recipient render (this caller passes no recipientName, so flipping renders <AddressLink> with an undefined address) and selects the "to" prefix over "for" — both correct for a send to an address. Only the title needed reframing, so isFromSendFlow is deliberately narrow.
  • useSendFlowOrigin replaces four copies of the marker rule that had drifted into three different definitions (['bank','crypto'].includes(m) vs m === 'bank' vs m === 'bank' && flow === 'withdraw'). That drift is how the screens came apart. Each call site keeps its own local guard, so this is a zero-behaviour-change consolidation.
  • Back/redirect targets now preserve ?method=. Otherwise back from the recipient screen lands on a bare /withdraw and the amount step silently reverts to withdraw copy — the same bug one hop earlier.

Smell verdict — adds none; reveals one, deliberately not fixed here. This PR gives the
marker a single reader (useSendFlowOrigin), but nothing owns writing it: the
?method=… query string is now hand-built at six call sites (three pre-existing, three
added here). A sendFlowQuery() writer alongside the hook would close that, but doing it
properly means editing the three pre-existing sites too — scope creep on a copy fix. The
three new sites deliberately match the surrounding style, so this is not made worse.
Worth a small follow-up, and it would be the natural companion to the deferred Manteca work.

Risks / breaking changes

Low — copy and one optional prop only. No route, ledger, transaction, or backend behaviour is touched. isFromSendFlow defaults to false everywhere, so every existing caller keeps today's wording. No cross-repo action needed.

The one behaviour worth reviewing: back-navigation targets from /withdraw/crypto now carry ?method=crypto when the user came from send.

QA

  • Send → Exchange or Wallet → amount → recipient / confirm / CTA / success all read Send / You're sending.
  • Send → Bank → same, end to end.
  • Regression: /withdraw directly (no ?method=) still reads Withdraw / You're withdrawing everywhere — this is the half d532b6a65 was protecting.
  • Success screen still reads "to 0x…", not "for".

Gate: prettier ✅ · typecheck ✅ · 206 suites / 2647 tests ✅ · next build ✅ · eslint 0 new errors (5 remaining warnings are pre-existing exhaustive-deps in touched files).

Tests

  • src/hooks/useSendFlowOrigin.test.ts — the marker rule, incl. that an unrecognised method (e.g. pix) must not read as a send.
  • src/components/Global/PeanutActionDetailsCard/__tests__/index.test.tsx — the regression guard against the ping-pong, covering both WITHDRAW and WITHDRAW_BANK_ACCOUNT in both framings. Verified non-vacuous by mutation: removing the fix fails exactly the two send assertions.
  • withdraw-states.test.tsx — asserts the ?method=crypto marker survives the Continue hop, which is the hop that dropped it.

Out of scope

Manteca (Pix / Mercado Pago) — reached from Send → Pix / Mercado Pago and has the identical defect, but withdraw/manteca/page.tsx never reads ?method= at all and carries ~6 hardcoded withdraw strings plus its own success screen. Deferred deliberately; useSendFlowOrigin makes it a small follow-up.


Screenshots

Captured against a real local sandbox

Send → Exchange or Wallet, recipient step
image
image

Header reads Send; card reads You're sending. Before this PR the same screen read
Withdraw / You're withdrawing — the user had just come from a step that said "Send".

Also verified live in the same session:

  • /withdraw?method=crypto"Send" / "Amount to send"
  • Continue → navigates to /withdraw/crypto?method=crypto, marker intact
  • Bouncing off /withdraw/crypto returns to /withdraw?method=crypto — pre-PR this went to a bare /withdraw and flipped back to "Withdraw"
  • Regression: bare /withdraw (no marker) still reads "Withdraw" — the half d532b6a65 was protecting

Before → after

Entering via Send → Exchange or Wallet (?method=crypto) or Send → Bank (?method=bank):

Screen Element Before After
Amount header / heading Send / Amount to send (unchanged — already correct)
Recipient (Initial.withdraw.view) NavHeader Withdraw Send
Recipient card title You're withdrawing You're sending
Confirm (Confirm.withdraw.view) NavHeader Withdraw Send
Confirm card title You're withdrawing You're sending
Confirm CTA (idle) Withdraw Send
Confirm CTA (processing) Withdrawing Sending
Success header Withdraw Send
Success title You just withdrew You just sent
Success amount prefix to 0x… (unchanged — "to" is correct)
Bank review card title You're withdrawing You're sending
Bank review CTA Withdraw Send
Bank success title You just withdrew You just sent

Entering via /withdraw directly (no ?method=): every one of the above is unchanged. That regression is covered by unit tests and is the half d532b6a65 was protecting.

Translations added for es-419 and pt-BR alongside en. es-AR is a 2 KB partial locale that does not carry the sibling youreWithdrawing / withdrew keys either, so it is intentionally untouched and falls back.

Summary by CodeRabbit

  • New Features

    • Improved send-flow navigation across bank and crypto withdrawals.
    • Send actions now retain their originating method when navigating between steps.
    • Updated titles, buttons, loading states, action details, and success messages to reflect “sending” versus “withdrawing.”
    • Added English, Spanish (Latin America), and Portuguese (Brazil) translations.
  • Bug Fixes

    • Fixed navigation losing the selected send method during withdrawal flows.
  • Tests

    • Added regression coverage for send-method preservation and send-flow messaging.

Send has no destination screens of its own — SendRouter navigates into the
withdraw routes (`/withdraw?method=crypto`, `?method=bank`), so `?method=` is
the only signal that the user framed this as a send. `/withdraw` honours it
("Send", "Amount to send") and forwards it to `/withdraw/crypto?method=crypto`,
but that page never read searchParams. The marker arrived and was dropped, so
every screen after the amount step reverted to withdraw copy: pick
Send → Exchange or Wallet, and the next screen says "You're withdrawing".

The word itself is not the bug. PeanutActionDetailsCard maps one
transactionType to one title, and WITHDRAW is genuinely both a withdrawal and
a send depending on how the user arrived — so it has already been flipped in
opposite directions twice (abd71b8 → "sending", d532b6a → "withdrawing"),
each engineer right about the flow in front of them. Flipping it a third time
would just re-break the real withdraw flow. Give the card the discriminator it
was missing instead.

isFromSendFlow is a narrow presentation flag, not a new transactionType: the
transaction really is a withdraw, and arrow-up/wallet-outline are already
correct for both framings, so only the verb branches. Same reason
PaymentSuccessView keeps isWithdrawFlow — it also suppresses the recipient
render and picks the "to" prefix, both right for a send to an address.

useSendFlowOrigin replaces four copies of the marker rule that had drifted into
three different definitions, which is how the screens came apart in the first
place. Manteca (Pix/Mercado Pago) has the same defect on its own page and is a
deliberate follow-up.
@vercel

vercel Bot commented Aug 6, 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 Aug 6, 2026 2:19pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f6a8e074-c9ba-4d50-a1cc-9ba7dc051ff3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The withdrawal flow now uses useSendFlowOrigin to preserve send-flow context. Withdrawal views, action cards, and success screens render send-specific labels. Crypto and bank navigation retain method markers. Tests and translations cover the new behavior.

Changes

Send-flow withdrawal framing

Layer / File(s) Summary
Centralized send-flow origin detection
src/hooks/useSendFlowOrigin.ts, src/hooks/useSendFlowOrigin.test.ts, src/app/(mobile-ui)/withdraw/page.tsx, src/components/AddWithdraw/*
useSendFlowOrigin derives bank and crypto origin flags from the method query parameter. Withdrawal entry components use the shared hook.
Send-specific withdrawal presentation
src/components/Global/PeanutActionDetailsCard/*, src/components/Withdraw/views/*, src/features/payments/shared/components/PaymentSuccessView.tsx, src/i18n/app/messages/*.json
Withdrawal views and payment success states accept isFromSendFlow and display send-specific titles and labels. English, Spanish, and Portuguese translations include the new strings.
Origin-aware withdrawal routing
src/app/(mobile-ui)/withdraw/crypto/page.tsx, src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx, src/components/AddWithdraw/DynamicBankAccountForm.tsx, src/app/(mobile-ui)/withdraw/__tests__/withdraw-states.test.tsx
Crypto and bank navigation preserve method markers and propagate send-flow state. Regression coverage verifies crypto navigation.

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

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: innolope-dev, kushagrasarathe, hugo0

Sequence Diagram(s)

sequenceDiagram
  participant SendFlow
  participant WithdrawPage
  participant WithdrawView
  participant PaymentSuccessView
  SendFlow->>WithdrawPage: Open withdrawal with method marker
  WithdrawPage->>WithdrawView: Pass isFromSendFlow
  WithdrawView->>PaymentSuccessView: Continue with send-flow state
  PaymentSuccessView-->>SendFlow: Render send-specific success title
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes preserving send-flow framing beyond the amount step, which is the pull request's main change.
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.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/send-flow-withdraw-copy

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

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 7056.43 → 7064.45 (+8.02)
Findings: +3 net (+101 new, -98 resolved)

🆕 New findings (101)

  • critical complexity — src/components/AddWithdraw/DynamicBankAccountForm.tsx — CC 152, MI 51.95, SLOC 465
  • critical complexity — src/components/AddWithdraw/AddWithdrawCountriesList.tsx — CC 122, MI 56.36, SLOC 370
  • critical complexity — src/app/(mobile-ui)/withdraw/page.tsx — CC 121, MI 53.24, SLOC 364
  • critical complexity — src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx — CC 104, MI 53.33, SLOC 386
  • critical complexity — src/app/(mobile-ui)/withdraw/crypto/page.tsx — CC 94, MI 50.61, SLOC 415
  • critical complexity — src/components/AddWithdraw/AddWithdrawRouterView.tsx — CC 88, MI 57.45, SLOC 244
  • critical complexity — src/components/Global/PeanutActionDetailsCard/index.tsx — CC 87, MI 55.03, SLOC 114
  • critical complexity — src/features/payments/shared/components/PaymentSuccessView.tsx — CC 59, MI 55.8, SLOC 172
  • high hotspot — src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx — 58 commits, +579/-290 lines since 6 months ago
  • high hotspot — src/components/AddWithdraw/AddWithdrawCountriesList.tsx — 50 commits, +738/-537 lines since 6 months ago
  • high complexity — src/components/Withdraw/views/Confirm.withdraw.view.tsx — CC 48, MI 57.56, SLOC 76
  • high complexity — src/components/Withdraw/views/Initial.withdraw.view.tsx — CC 44, MI 57.73, SLOC 145
  • high method-complexity — src/components/AddWithdraw/DynamicBankAccountForm.tsx:175 — CC 43 SLOC 124
  • high hotspot — src/app/(mobile-ui)/withdraw/crypto/page.tsx — 38 commits, +498/-255 lines since 6 months ago
  • high method-complexity — src/components/AddWithdraw/DynamicBankAccountForm.tsx:79 — CC 35 SLOC 201
  • high method-complexity — src/components/Withdraw/views/Confirm.withdraw.view.tsx:69 — ConfirmWithdrawView CC 31 SLOC 53
  • medium react-long-component — src/app/(mobile-ui)/withdraw/crypto/page.tsx:44 — WithdrawCryptoPage is 656 lines — split it
  • medium react-long-component — src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx:56 — WithdrawBankPage is 575 lines — split it
  • medium react-long-component — src/app/(mobile-ui)/withdraw/page.tsx:29 — WithdrawPage is 456 lines — split it
  • medium high-mdd — src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx:56 — WithdrawBankPage: MDD 210.1 (uses across many lines from declarations)

…and 81 more.

✅ Resolved (98)

  • src/components/AddWithdraw/DynamicBankAccountForm.tsx — CC 150, MI 52.05, SLOC 461
  • src/app/(mobile-ui)/withdraw/page.tsx — CC 124, MI 53.2, SLOC 363
  • src/components/AddWithdraw/AddWithdrawCountriesList.tsx — CC 123, MI 56.31, SLOC 371
  • src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx — CC 101, MI 53.4, SLOC 385
  • src/app/(mobile-ui)/withdraw/crypto/page.tsx — CC 92, MI 50.79, SLOC 409
  • src/components/AddWithdraw/AddWithdrawRouterView.tsx — CC 88, MI 57.48, SLOC 243
  • src/components/Global/PeanutActionDetailsCard/index.tsx — CC 86, MI 55.15, SLOC 113
  • src/features/payments/shared/components/PaymentSuccessView.tsx — CC 58, MI 55.88, SLOC 171
  • src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx — 56 commits, +562/-279 lines since 6 months ago
  • src/components/AddWithdraw/AddWithdrawCountriesList.tsx — 48 commits, +732/-534 lines since 6 months ago
  • src/components/Withdraw/views/Confirm.withdraw.view.tsx — CC 45, MI 57.84, SLOC 75
  • src/components/Withdraw/views/Initial.withdraw.view.tsx — CC 43, MI 57.85, SLOC 144
  • src/components/AddWithdraw/DynamicBankAccountForm.tsx:171 — CC 42 SLOC 124
  • src/app/(mobile-ui)/withdraw/crypto/page.tsx — 36 commits, +476/-249 lines since 6 months ago
  • src/components/AddWithdraw/DynamicBankAccountForm.tsx:78 — CC 34 SLOC 197
  • src/app/(mobile-ui)/withdraw/crypto/page.tsx:43 — WithdrawCryptoPage is 641 lines — split it
  • src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx:55 — WithdrawBankPage is 570 lines — split it
  • src/app/(mobile-ui)/withdraw/page.tsx:28 — WithdrawPage is 458 lines — split it
  • src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx:55 — WithdrawBankPage: MDD 207.4 (uses across many lines from declarations)
  • src/components/AddWithdraw/DynamicBankAccountForm.tsx:78 — : MDD 192.0 (uses across many lines from declarations)

…and 78 more.

📈 Painscore deltas (top movers)

File Before After Δ
src/hooks/useSendFlowOrigin.ts 0.0 5.7 +5.7

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • unit: 2660 ran, 0 failed, 0 skipped, 47.1s

📊 Coverage (unit)

metric %
statements 64.3%
branches 48.5%
functions 53.9%
lines 64.9%
⏱ 10 slowest test cases
time test
3.5s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › never places two stickers in heavy overlap (broad seed sweep)
1.2s src/utils/__tests__/demo-api.test.ts › isDemoMode() is false when not running under Capacitor
0.5s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › every sticker stays within canvas at any count
0.3s src/utils/__tests__/sentry.utils.test.ts › defaults to the client budget under a browser global
0.3s src/utils/__tests__/auth-token.test.ts › ignores the guarded marker and falls back to the plain token
0.3s src/app/(mobile-ui)/withdraw/__tests__/withdraw-states.test.tsx › Bank withdrawal keeps the $1 minimum for sub-$1 amounts
0.3s src/utils/__tests__/sentry.utils.test.ts › still lets a per-call timeoutMs win over the default
0.3s src/utils/__tests__/auth-token.test.ts › is none — never guarded — when only the guarded marker is present
0.3s src/app/actions/__tests__/api-headers.test.ts › should include Content-Type in validateInviteCode
0.3s src/utils/__tests__/auth-token.test.ts › returns the token hydrated from Preferences after authReady
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

@abalinda

abalinda commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 6, 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.

@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: 2

🤖 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/app/`(mobile-ui)/withdraw/[country]/bank/page.tsx:
- Line 451: Update the primary CTA label in the bank page to use fromSendFlow,
so send flows display “Send” consistently with the header and action card while
other flows retain “Withdraw”.

In `@src/components/AddWithdraw/DynamicBankAccountForm.tsx`:
- Around line 107-109: The existing-account redirect in
DynamicBankAccountForm.tsx must append method=bank when framedAsSend is true. In
src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx, update both the no-amount
and no-account redirects to preserve method=bank when fromSendFlow is true;
leave other redirect behavior unchanged.
🪄 Autofix

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: c0ba862c-08fd-4b9a-a66f-d09c542f3151

📥 Commits

Reviewing files that changed from the base of the PR and between 2a7df35 and e6006fa.

📒 Files selected for processing (17)
  • src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx
  • src/app/(mobile-ui)/withdraw/__tests__/withdraw-states.test.tsx
  • src/app/(mobile-ui)/withdraw/crypto/page.tsx
  • src/app/(mobile-ui)/withdraw/page.tsx
  • src/components/AddWithdraw/AddWithdrawCountriesList.tsx
  • src/components/AddWithdraw/AddWithdrawRouterView.tsx
  • src/components/AddWithdraw/DynamicBankAccountForm.tsx
  • src/components/Global/PeanutActionDetailsCard/__tests__/index.test.tsx
  • src/components/Global/PeanutActionDetailsCard/index.tsx
  • src/components/Withdraw/views/Confirm.withdraw.view.tsx
  • src/components/Withdraw/views/Initial.withdraw.view.tsx
  • src/features/payments/shared/components/PaymentSuccessView.tsx
  • src/hooks/useSendFlowOrigin.test.ts
  • src/hooks/useSendFlowOrigin.ts
  • src/i18n/app/messages/en.json
  • src/i18n/app/messages/es-419.json
  • src/i18n/app/messages/pt-BR.json

Comment thread src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx
Comment thread src/components/AddWithdraw/DynamicBankAccountForm.tsx
CodeRabbit caught two instances of the exact seam this PR exists to close,
on the bank side rather than the crypto side.

The bank review CTA still read "Withdraw" while the header and amount card
above it already read "Send" — the same screen disagreeing with itself.

Three bank redirects also dropped ?method=bank, so the step the user was sent
back to silently reverted to withdraw copy: the existing-saved-account push in
DynamicBankAccountForm, and the no-amount / no-account replaces in the bank
page. A fourth in the same file (the unsupported-country bounce) had the same
defect and is fixed here too; that one needed the hook hoisted above the
effect that uses it.
@abalinda

abalinda commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 6, 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.

@abalinda

abalinda commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

(The incremental pass reported "does not re-review already reviewed commits" and did not look at 5a907d9ed, which is where the two findings were actually fixed. Requesting a full pass over the current head.)

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@abalinda I will run a full review of the current head. This review includes commit 5a907d9ed.

✅ Action performed

Full review finished.

@abalinda
abalinda marked this pull request as ready for review August 6, 2026 11:36
Copilot AI lite review requested due to automatic review settings August 6, 2026 11:36

@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: 2

🤖 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/AddWithdraw/AddWithdrawCountriesList.tsx`:
- Around line 57-59: Update the isBankFromSend value in AddWithdrawCountriesList
to only be true when the current flow is withdraw, matching
AddWithdrawRouterView; ensure the guarded value passed to
CountryList.enforceSupportedCountries does not apply send-only filtering to
add-money users.

In `@src/components/AddWithdraw/DynamicBankAccountForm.tsx`:
- Around line 445-446: Update the component props around isFromSendFlow so
actionDetailsProps is spread before the explicit isFromSendFlow={framedAsSend}
prop, or remove that key from actionDetailsProps, ensuring the flow-derived
value remains authoritative.
🪄 Autofix

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: 0672ec1a-64e3-444a-b8ec-8be979fe84f2

📥 Commits

Reviewing files that changed from the base of the PR and between 2a7df35 and 5a907d9.

📒 Files selected for processing (17)
  • src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx
  • src/app/(mobile-ui)/withdraw/__tests__/withdraw-states.test.tsx
  • src/app/(mobile-ui)/withdraw/crypto/page.tsx
  • src/app/(mobile-ui)/withdraw/page.tsx
  • src/components/AddWithdraw/AddWithdrawCountriesList.tsx
  • src/components/AddWithdraw/AddWithdrawRouterView.tsx
  • src/components/AddWithdraw/DynamicBankAccountForm.tsx
  • src/components/Global/PeanutActionDetailsCard/__tests__/index.test.tsx
  • src/components/Global/PeanutActionDetailsCard/index.tsx
  • src/components/Withdraw/views/Confirm.withdraw.view.tsx
  • src/components/Withdraw/views/Initial.withdraw.view.tsx
  • src/features/payments/shared/components/PaymentSuccessView.tsx
  • src/hooks/useSendFlowOrigin.test.ts
  • src/hooks/useSendFlowOrigin.ts
  • src/i18n/app/messages/en.json
  • src/i18n/app/messages/es-419.json
  • src/i18n/app/messages/pt-BR.json

Comment thread src/components/AddWithdraw/AddWithdrawCountriesList.tsx Outdated
Comment thread src/components/AddWithdraw/DynamicBankAccountForm.tsx Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

/withdraw/crypto currently hard-codes the back/redirect marker to ?method=crypto, which can silently flip an incoming ?method=bank marker and alter back-navigation semantics in that edge path.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Pull request overview

This PR fixes inconsistent “Withdraw” vs “Send” framing when users enter the withdraw routes via the Send flow by preserving and consistently reading the ?method= marker across subsequent steps, and by adding a narrow presentation flag to reframe copy without changing transaction semantics.

Changes:

  • Introduces useSendFlowOrigin() to centralize detection of send-origin via ?method=bank|crypto.
  • Threads an isFromSendFlow presentation prop through withdraw recipient/confirm/success UI (including PeanutActionDetailsCard and PaymentSuccessView) to render “Send” copy when appropriate.
  • Adds/updates unit tests and i18n strings to prevent regressions and ensure the marker survives key navigation hops.
File summaries
File Description
src/i18n/app/messages/en.json Adds “sending” / “justSent” / “youreSending” strings used by reframed send copy.
src/i18n/app/messages/es-419.json Adds corresponding send-framing strings for es-419.
src/i18n/app/messages/pt-BR.json Adds corresponding send-framing strings for pt-BR.
src/hooks/useSendFlowOrigin.ts New hook: single owner for determining send-origin from ?method=.
src/hooks/useSendFlowOrigin.test.ts Tests the marker rule and guards against treating unknown methods as send.
src/features/payments/shared/components/PaymentSuccessView.tsx Adds isFromSendFlow to reframe the withdraw success title (“just sent” vs “withdrew”).
src/components/Withdraw/views/Initial.withdraw.view.tsx Adds isFromSendFlow to keep header/card copy consistent with Send framing.
src/components/Withdraw/views/Confirm.withdraw.view.tsx Adds isFromSendFlow to keep header/CTA/loading copy consistent with Send framing.
src/components/Global/PeanutActionDetailsCard/index.tsx Adds isFromSendFlow to disambiguate “You’re withdrawing” vs “You’re sending” for withdraw transaction types.
src/components/Global/PeanutActionDetailsCard/tests/index.test.tsx New regression tests for withdraw-vs-send title branching on isFromSendFlow.
src/components/AddWithdraw/DynamicBankAccountForm.tsx Preserves ?method=bank on navigation to keep downstream screens framed as Send when applicable.
src/components/AddWithdraw/AddWithdrawRouterView.tsx Consolidates send-origin logic via the hook (with local flow guard).
src/components/AddWithdraw/AddWithdrawCountriesList.tsx Consolidates bank-from-send detection via the hook.
src/app/(mobile-ui)/withdraw/page.tsx Replaces ad-hoc marker parsing with useSendFlowOrigin() in the withdraw amount step.
src/app/(mobile-ui)/withdraw/crypto/page.tsx Reads send-origin and preserves marker on back/redirect; threads isFromSendFlow into subviews/success.
src/app/(mobile-ui)/withdraw/[country]/bank/page.tsx Reads send-origin via the hook and preserves marker across redirects/CTAs/success.
src/app/(mobile-ui)/withdraw/tests/withdraw-states.test.tsx Adds regression test that the ?method=crypto marker is forwarded to /withdraw/crypto.
Review details
  • Files reviewed: 17/17 changed files
  • Comments generated: 1
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Comment thread src/app/(mobile-ui)/withdraw/crypto/page.tsx Outdated
Three follow-ups from CodeRabbit's full pass, all cases of the marker being
read too eagerly rather than too little.

The marker alone doesn't mean "send": the add-money flow navigates with its
own ?method=bank, so AddWithdrawCountriesList — which serves both flows —
needs the same `flow === 'withdraw'` guard its sibling AddWithdrawRouterView
already had. (CodeRabbit's stated consequence pointed at
enforceSupportedCountries, which actually lives in the sibling and was already
guarded; the guard is still right here for the navigation branches.) Behaviour
is unchanged from before this PR — the previous expression had the same gap.

Entering as /withdraw?method=bank and then picking Crypto lands on
/withdraw/crypto?method=bank, where the back target hard-coded ?method=crypto
and silently rewrote the marker, changing the amount step's back behaviour.
The hook now exposes the raw value so callers forward it verbatim instead of
re-deriving it.

actionDetailsProps is a Partial of the card's full props, so now that
isFromSendFlow is one of them a caller could override the flow-guarded value.
Moved after the spread to keep the derived value authoritative.
@abalinda
abalinda requested a lite review from Copilot August 6, 2026 11:49

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@abalinda

abalinda commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Review rate limited.


Your included review limit is currently reached under our Fair Usage Limits Policy. Your recent PR review activity is in the 95th percentile or higher among CodeRabbit users, so adaptive limits apply. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 35 minutes.

@abalinda

abalinda commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@kushagrasarathe

Copy link
Copy Markdown
Contributor

Agent review — advisory (T2)

Verdict: approve-advisory. High-quality, well-tested, correctly-scoped fix that answers a real recurring smell the right way. No breakage, perf, or security concerns. One gate: add a task link.

Risk tier

  • T2 — send/withdraw money-movement flow, but copy + one presentation flag only (no logic/route/ledger change). Author is established (17 commits on dev), so not T0. Full read + all four checklists applied.

Paired PR

  • none — FE-only. isFromSendFlow defaults to false everywhere, so every existing caller keeps today's wording. No cross-repo action needed (correctly stated).

A. Breakage — pass (one nuance)

  • The 2nd arg added to withdrawCountryUrl / withdrawBankUrl is genuinely honored: native-routes.ts already declares queryParams?: string and appends it for both the Capacitor (&) and web (?) forms (native-routes.ts:57,65). The marker is propagated, not dropped.
  • searchParams in bank/page.tsx is still used (line 91) after removing methodParam — no dangling var.
  • useSendFlowOrigin is behavior-equivalent to the old inline logic at withdraw/page.tsx and AddWithdrawRouterView. typecheck + unit + e2e all green.
  • Nuance: AddWithdrawCountriesList.tsx:226 adds && flow === 'withdraw' that the old code there did not have (old isBankFromSend = method==='bank' unconditionally). This tightens a prior false-positive in the add-money flow (where ?method=bank also occurs) — a net-positive latent fix, but it means the "zero-behaviour-change consolidation" claim is slightly overstated for that one site. Low risk; worth a one-line acknowledgement, ideally an add-money back-nav sanity check.

B. Performance — pass

  • Hook reads useSearchParams; no loops, queries, or render-path cost.

C. Quality — pass (exemplary)

  • Fifth-bug rule: PeanutActionDetailsCard's WITHDRAW title was flipped in opposite directions twice (abd71b882d532b6a65). This PR does the right thing with that smell — adds the missing isFromSendFlow discriminator instead of flipping a third time, and lands a mutation-verified regression test covering both WITHDRAW and WITHDRAW_BANK_ACCOUNT in both framings. This is how the fifth-bug signal should be answered.
  • Reuse/DRY: useSendFlowOrigin collapses 4 drifted copies of the marker rule (3 different definitions) into one owner — directly removes the drift that caused the bug.
  • Honest scope: self-identifies the remaining smell (marker has a reader but no writer; 6 hand-built ?method= sites) and defers it rather than scope-creeping. Manteca/Pix deferred with a clear reason.
  • Comments explain the non-obvious calls (why isWithdrawFlow stays true; why the marker is forwarded verbatim rather than rewritten to crypto).

D. Security — pass

  • No routes, auth, PII, or secrets. Copy + one optional presentation prop.

CI note

Task link — gate

  • No Notion/issue link in the PR body. Add a task link before merge.

Bottom line

The model of how to handle a ping-ponged line — it stops the flip-war by adding the discriminator both prior authors were missing, proves it with a mutation-checked regression test, and consolidates the drifted rule into a single hook. Genuinely strong work.

Automated advisory review.

@kushagrasarathe kushagrasarathe 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.

Approved on behalf of @kushagrasarathe (human reviewer).

No blocking defects. Required CI gates (typecheck, unit, e2e, format, deploy) are green; the eslint failure is the same pre-existing dev debt (ReConsentModal / AdvisoryPreemptModal, both untouched here) — 0 new errors from this PR.

This is the right resolution to a line that had been flipped twice (abd71b8d532b6a): it adds the missing isFromSendFlow discriminator instead of flipping a third time, with a mutation-verified regression test.

Follow-ups (non-blocking):

  1. Add a task link to the PR body.
  2. Optional: acknowledge that AddWithdrawCountriesList's added && flow === 'withdraw' guard isn't strictly zero-behaviour — it's a good change (fixes an add-money false-positive), just name it.

Full review: see the review comment on this PR.

dev landed six i18n commits, including a pass that dedups app copy across
locales. One real conflict, in es-419's peanutActionDetailsCard block: this
branch added `youreSending` while dev retranslated `youWillReceive`
("Recibirás" -> "Vas a recibir").

Resolved as a union — dev's retranslation wins for its own key, this branch's
new key is kept. Neither side loses an entry, which is the hazard git flags
here.

Everything else auto-merged, including dev's `t('confirm.sponsoredByPeanut')`
-> `tCommon('sponsoredByPeanut')` move inside Confirm.withdraw.view.tsx, which
sits next to this branch's CTA change in the same file.
@abalinda
abalinda merged commit 6f3bb33 into dev Aug 6, 2026
18 of 20 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.

3 participants