Skip to content

fix(trade): preserve visible recipient URL flow#7611

Open
fairlighteth wants to merge 1 commit into
fix/deepsec-high-frontend-hardeningfrom
fix/recipient-url-initialization-followup
Open

fix(trade): preserve visible recipient URL flow#7611
fairlighteth wants to merge 1 commit into
fix/deepsec-high-frontend-hardeningfrom
fix/recipient-url-initialization-followup

Conversation

@fairlighteth

@fairlighteth fairlighteth commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up on #7601 to restore the supported visible custom recipient URL flow without weakening the hardening.

This PR fixes an existing regression already present on production and develop: ?recipient=<value> shows the visible recipient section, but the field gets cleared during initialization and ends up empty.

This is a bug fix, not a behavior change. recipient=<value> was already the intended supported visible URL flow. The PR keeps recipientAddress intentionally unsupported from the URL, but preserves recipient=<value> so the visible recipient section stays populated after initialization instead of being cleared on mount.

What changed:

  • keep the PR fix: harden frontend security entrypoints #7601 hardening that does not trust hidden recipientAddress from the URL
  • keep recipientAddress=... from activating recipient mode by itself
  • preserve recipient=<value> as the supported visible custom recipient URL flow
  • add targeted regression coverage for URL parsing, recipient visibility, and mount/reset behavior

Automated verification:

  • pnpm exec jest --config apps/cowswap-frontend/jest.config.mjs --runInBand apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeStateFromUrl.test.ts apps/cowswap-frontend/src/modules/trade/hooks/useResetRecipient.test.ts apps/cowswap-frontend/src/modules/trade/hooks/useWithRecipient.test.ts
  • pnpm exec eslint apps/cowswap-frontend/src/modules/trade/hooks/useResetRecipient.ts apps/cowswap-frontend/src/modules/trade/hooks/useResetRecipient.test.ts apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeStateFromUrl.test.ts apps/cowswap-frontend/src/modules/trade/hooks/useWithRecipient.test.ts

To Test

  1. Empty visible recipient param

Open:
#/1/swap/WETH/1INCH?recipient=

  • Recipient mode does not activate
  • Recipient input is not shown
  • No recipient value is populated
  1. Hidden recipientAddress param remains unsupported

Open:
#/1/swap/WETH/1INCH?recipientAddress=0x000000000000000000000000000000000000dEaD

  • Recipient mode does not activate from this param alone
  • Recipient input is not shown
  • No recipient value is populated from the URL
  1. Supported visible recipient param stays populated for EVM

Open:
#/1/swap/WETH/1INCH?recipient=0x000000000000000000000000000000000000dEaD

  • Recipient mode is visible
  • Recipient input stays populated with 0x000000000000000000000000000000000000dEaD
  • The value is not cleared during initial mount / wallet chain initialization
  1. Supported visible recipient param stays populated for Solana

Open:
#/1/swap/WETH/CtzPWv73Sn1dMGVU3ZtLv9yWSyUAanBni19YWDaznnkn?targetChainId=1000000001&recipient=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v

  • Recipient mode is visible
  • Recipient input stays populated with EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
  • The recipient is recognized as a valid Solana address
  • The value is not cleared during initial mount / wallet chain initialization
  1. Supported visible recipient param stays populated for Bitcoin

Open:
#/1/swap/WETH/1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa?targetChainId=1000000000&recipient=bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4

  • Recipient mode is visible
  • Recipient input stays populated with bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
  • The recipient is recognized as a valid Bitcoin address
  • The value is not cleared during initial mount / wallet chain initialization

Background

This regression already exists in production/develop today. The supported visible URL param recipient is still present in URL state and still controls whether the recipient UI appears, but the live recipient value gets cleared during initialization.

useIsWithRecipient() still uses URL recipient to decide whether the visible recipient UI should appear, which is the intended supported flow.

The bug was in useResetRecipient(): generic reset effects were still clearing the live recipient state during initialization, so the UI could appear while the field ended up empty.

This change only preserves URL-backed visible recipients through initialization. It does not reintroduce support for hidden recipientAddress URL state.

- keep URL-driven visible recipients populated after mount
- add regression coverage for recipient URL parsing and reset flow
@vercel

vercel Bot commented Jun 5, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
cowfi Ready Ready Preview Jun 5, 2026 11:07am
explorer-dev Ready Ready Preview Jun 5, 2026 11:07am
sdk-tools Ready Ready Preview Jun 5, 2026 11:07am
storybook Ready Ready Preview Jun 5, 2026 11:07am
swap-dev Ready Ready Preview Jun 5, 2026 11:07am
widget-configurator Ready Ready Preview Jun 5, 2026 11:07am
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
cosmos Ignored Ignored Jun 5, 2026 11:07am

Request Review

@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2afd65c4-adba-46a3-9f92-0bfcd9bde61e

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/recipient-url-initialization-followup

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 and usage tips.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying explorer-dev with  Cloudflare Pages  Cloudflare Pages

Latest commit: b9c02ce
Status: ✅  Deploy successful!
Preview URL: https://670c2b92.explorer-dev-dxz.pages.dev
Branch Preview URL: https://fix-recipient-url-initializa.explorer-dev-dxz.pages.dev

View logs

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying swap-dev with  Cloudflare Pages  Cloudflare Pages

Latest commit: b9c02ce
Status: ✅  Deploy successful!
Preview URL: https://6dc4ac63.swap-dev-5u6.pages.dev
Branch Preview URL: https://fix-recipient-url-initializa.swap-dev-5u6.pages.dev

View logs

@fairlighteth fairlighteth self-assigned this Jun 5, 2026
@fairlighteth

Copy link
Copy Markdown
Contributor Author
AI Review (Codex GPT-5, worked 1m32s): no new non-duplicate findings

I rechecked the current diff and did not find any new non-duplicate issues worth posting.

Review scope and related context

Checked:

  • apps/cowswap-frontend/src/modules/trade/hooks/useResetRecipient.ts
  • apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeStateFromUrl.test.ts
  • apps/cowswap-frontend/src/modules/trade/hooks/useResetRecipient.test.ts
  • apps/cowswap-frontend/src/modules/trade/hooks/useWithRecipient.test.ts

Notes:

  • The change stays scoped to restoring the supported visible recipient URL flow while keeping hidden recipientAddress intentionally unsupported.
  • The added tests cover URL parsing plus the mount/reset regression that was clearing the live recipient state.
  • Solana and Bitcoin verification is documented in the PR QA section and appears to be covered manually.
  • The currently red CI checks do not appear to point to a new failure introduced by these touched files.

@fairlighteth

fairlighteth commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author
PR - Automated QA (Codex GPT-5, worked 2h): recipient URL initialization verified for EVM and Solana; BTC refresh caveat noted

Outcome

  • Passed: empty recipient= does not enable recipient mode
  • Passed: hidden recipientAddress= remains unsupported
  • Passed: visible EVM recipient= stays populated
  • Passed: corrected Solana recipient= route stays populated and shows the non-EVM confirmation UI in Chromium and Firefox
  • Follow-up note: Bitcoin can reach the correct recipient state, but hard refresh on preview is still confounded by a separate bridge-route bootstrap quirk

Source under test

  • Browser-based verification was performed locally with Playwright against the deployed PR preview at commit b9c02ce from June 5, 2026.
  • I did not use the local worktree as source under test because local HEAD was 1dfa17c on worktree/7611-qa / develop, not the PR head branch.
  • Results were visually inspected from captured screenshots.

Environment:

  • Browsers: Chromium 148.0.7778.96, Firefox 150.0.2
  • OS: Linux

Wallet state reached:

  • disconnected: yes
  • provider-injected: no
  • wallet-connected-ui: no
  • signing-capable: no

If re-running locally:

  • Preview used: https://fix-recipient-url-initializa.swap-dev-5u6.pages.dev
  • No local state required
  • If the preview first lands on the marketing shell, click Swap now once to enter the widget before checking the recipient row

Expected results:

  1. Open #/1/swap/WETH/1INCH?recipient=
    Expected: recipient mode stays off and no recipient field is shown
  2. Open #/1/swap/WETH/1INCH?recipientAddress=0x000000000000000000000000000000000000dEaD
    Expected: hidden recipientAddress stays unsupported and no recipient field is shown
  3. Open #/1/swap/WETH/1INCH?recipient=0x000000000000000000000000000000000000dEaD
    Expected: recipient row is visible and stays populated with that address
  4. Open #/1/swap/DAI/EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm?recipient=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v&targetChainId=1000000001
    Expected: Solana recipient row is visible, populated, and shows the confirmation UI

Browser coverage:

  • Chromium 148.0.7778.96: empty recipient= passed; unsupported recipientAddress= passed; EVM recipient= passed; corrected Solana URL passed
  • Firefox 150.0.2: corrected Solana URL passed

Why these adjacent flows were included:

  • Empty recipient shares the same URL parsing and recipient-visibility boundary
  • Hidden recipientAddress is part of the PR’s stated hardening boundary
  • Cross-browser Solana coverage exercises the riskiest non-EVM initialization path claimed by the PR

Artifacts:

  • Chromium EVM recipient success
Chromium EVM recipient success
  • Chromium Solana recipient success
Chromium Solana recipient success
  • Firefox Solana recipient success
Firefox Solana recipient success
Note: Bitcoin refresh-specific bootstrap quirk

Impact:

  • The PR’s intended recipient-preservation behavior was verified for EVM and Solana, but Bitcoin hard refresh on preview is still confounded by separate bridge-route bootstrap behavior.

Observed behavior:

  • A hard refresh on the BTC URL could rewrite the hash to #/1/swap/WETH?recipient=..., drop the BTC output route, and leave the recipient as a plain invalid text field.
  • Re-entering the exact same BTC URL in an already-loaded tab could reach the correct BTC recipient state with checkmark and confirmation row.

Interpretation:

  • This looks more like a separate cold-bootstrap bridge-route normalization issue than a regression in the touched useResetRecipient code.
  • I did not treat that as blocking this PR’s recipient-reset fix, but it is worth keeping as follow-up context for manual QA.

Reference screenshots:

  • Chromium BTC hard-refresh invalid state
Chromium BTC hard-refresh invalid state
  • Firefox BTC hard-refresh invalid state
Firefox BTC hard-refresh invalid state

Commands run:

  • gh pr view 7611 --json title,body,files,comments,reviews,headRefName,baseRefName,url,commits
  • git rev-parse --abbrev-ref HEAD
  • git rev-parse HEAD
  • cd /tmp/pr-qa-7611 && npm install playwright@latest
  • npx playwright install chromium firefox
  • node /tmp/pr-qa-7611/qa-7611.js
  • Follow-up Playwright reruns against the exact EVM, Solana, and Bitcoin preview URLs discussed in QA

Residual gaps:

  • Local PR-branch dev server was not used because the current worktree did not match the PR head
  • Bitcoin cold-refresh behavior remains inconsistent on preview and appears confounded by separate bridge bootstrap logic

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.

1 participant