Skip to content

feat(bridge): enable sell=buy feature#7633

Open
shoom3301 wants to merge 11 commits into
developfrom
feat/sell-buy-2
Open

feat(bridge): enable sell=buy feature#7633
shoom3301 wants to merge 11 commits into
developfrom
feat/sell-buy-2

Conversation

@shoom3301

@shoom3301 shoom3301 commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

Coupled with cowprotocol/cow-sdk#897

With this change, cross-chain swaps should support intermediate token ~= destination token.
For example:
https://swap.cow.fi/#/8453/swap/USDC/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48?targetChainId=1
This will never route you USDC (Base) -> USDC (Base) -> USDC (Ethereum) because USDC (Base) -> USDC (Base) was not supported on the backend.

In this PR it should do such a route.

To Test

  1. Try swapping the same asset across different chains
  2. Try swapping native token across different chains
  • swaps and bridges should be successful

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Enabled same-token swap/trade behavior when hook/store settings allow it, including widget actions and trade state/currency selection flow.
    • Updated quote request settings to allow intermediate same-token sell behavior.
  • Bug Fixes

    • Improved quote error text and tooltip selection logic to remove bridge-specific mapping behavior.
  • Chores

    • Upgraded Cow Protocol SDK dependencies across apps and shared libraries.
    • Marked outdated English locale strings as obsolete.

@vercel

vercel Bot commented Jun 9, 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 15, 2026 4:22pm
explorer-dev Ready Ready Preview Jun 15, 2026 4:22pm
storybook Ready Ready Preview Jun 15, 2026 4:22pm
swap-dev Ready Ready Preview Jun 15, 2026 4:22pm
widget-configurator Ready Ready Preview Jun 15, 2026 4:22pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
cosmos Ignored Ignored Jun 15, 2026 4:22pm
sdk-tools Ignored Ignored Preview Jun 15, 2026 4:22pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 8dd98a26-9d47-4388-900d-7efc732de872

📥 Commits

Reviewing files that changed from the base of the PR and between 37d7133 and b5fc9c3.

⛔ Files ignored due to path filters (1)
  • apps/cowswap-frontend/src/modules/tradeQuote/hooks/__snapshots__/useTradeQuotePolling.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (1)
  • apps/cowswap-frontend/src/modules/tradeQuote/services/fetchAndProcessQuote.test.ts

Walkthrough

Bumps @cowprotocol/cow-sdk from 9.1.5 to 9.2.0 and several sdk-* packages across all monorepo workspace packages. Concurrently enables previously blocked features in cowswap-frontend: allowIntermediateEqSellToken in quote requests with updated test expectations, simplified bridge-error handling, and an enableSellEqBuy parameter threaded through the trade/swap widget system to conditionally allow same-token swaps when hooks are enabled; also adds allowSwapSameToken prop and marks two obsolete bridge locale strings.

Changes

SDK Upgrade and Feature Enablement

Layer / File(s) Summary
Feature prerequisites: quote, error, UI, locale cleanup, and tests
apps/cowswap-frontend/src/modules/tradeQuote/services/fetchAndProcessQuote.ts, apps/cowswap-frontend/src/modules/tradeQuote/services/fetchAndProcessQuote.test.ts, apps/cowswap-frontend/src/modules/tradeFormValidation/pure/QuoteApiErrorButton.pure.tsx, apps/cowswap-frontend/src/modules/hooksStore/containers/HooksStoreWidget/index.tsx, apps/cowswap-frontend/src/locales/en-US.po
fetchAndProcessQuote sets allowIntermediateEqSellToken: true (removing TODO) with updated test expectations in four test scenarios. QuoteApiErrorButton drops bridge-specific error mappings and uses quoteErrorTexts[errorType] ?? DEFAULT_ERROR_TEXT lookup. HooksStoreWidget adds allowSwapSameToken prop. Two bridge-related locale strings marked obsolete.
Swap-level hooks and widget entry points
apps/cowswap-frontend/src/modules/hooksStore/hooks/useSetRecipientOverride.ts, apps/cowswap-frontend/src/modules/swap/hooks/useSwapWidgetActions.ts, apps/cowswap-frontend/src/modules/swap/hooks/useOnCurrencySelection.ts, apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx
useSetRecipientOverride calls useSwapWidgetActions(true). useSwapWidgetActions now accepts isHooksStoreEnabled and forwards to useOnCurrencySelection. SwapWidget passes hooksEnabledState[0] to useSwapWidgetActions and adds enableSellEqBuy param to TradeWidget. Swap useOnCurrencySelection accepts and forwards enableSellEqBuy.
Trade widget type contract and container wiring
apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/types.ts, apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/index.tsx, apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetUpdaters.tsx, apps/cowswap-frontend/src/modules/trade/updaters/CommonTradeUpdater.tsx
TradeWidgetParams adds enableSellEqBuy?: boolean field. TradeWidget destructures and forwards to TradeWidgetUpdaters. TradeWidgetUpdaters props accept enableSellEqBuy and pass to CommonTradeUpdater. CommonTradeUpdater introduces CommonTradeUpdaterProps interface and receives prop.
Trade state and navigation hooks: enableSellEqBuy feature logic
apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeState.ts, apps/cowswap-frontend/src/modules/trade/hooks/useNavigateOnCurrencySelection.ts, apps/cowswap-frontend/src/modules/trade/hooks/useOnCurrencySelection.ts
useSetupTradeState accepts enableSellEqBuy, tracks it in a ref, and gates same-token reset on !enableSellEqBuyRef.current. useNavigateOnCurrencySelection accepts enableSellEqBuy and conditionally swaps currency IDs only when not enabled (allowing same-token navigation when enabled). Trade useOnCurrencySelection accepts and forwards parameter.
SDK dependency bumps across all packages
apps/cowswap-frontend/package.json, apps/explorer/package.json, apps/sdk-tools/package.json, apps/widget-configurator/package.json, libs/*/package.json
@cowprotocol/cow-sdk bumped 9.1.59.2.0 across all workspace packages. Additional bumps: sdk-bridging 4.1.34.2.0, sdk-contracts-ts 3.1.23.2.0, sdk-cow-shed 0.3.130.4.0, sdk-order-book 3.2.24.0.0, sdk-trading 2.1.22.2.0, sdk-viem-adapter 0.3.230.3.24, plus sdk-subgraph and sdk-composable bumps where present.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • cowprotocol/cowswap#7608: Introduces getQuoteErrorTexts() and quote error mapping utilities that QuoteApiErrorButton.pure.tsx now relies on.
  • cowprotocol/cowswap#6834: Implements the same SwapWidget/TradeWidget sell=buy flow for same-token swaps with hooks state threading.
  • cowprotocol/cowswap#5588: Modifies quote/bridge flow in fetchAndProcessQuote.ts to support bridging SDK; this PR extends it with allowIntermediateEqSellToken feature.

Suggested labels

Bridge

Suggested reviewers

  • elena-zh
  • alfetopito

Poem

🐇 Hop, hop — the SDK leaps to 9.2.0 today,
Bridge errors simplified, cast to the gray,
enableSellEqBuy threads through every hook,
Same tokens now swap with a feature-flag look,
Locale strings retire, TODO comments flee —
The rabbit bumped versions so traders live free! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.77% 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
Title check ✅ Passed The title 'feat(bridge): enable sell=buy feature' clearly and concisely describes the main change—enabling the sell=buy feature for bridge/cross-chain swaps.
Description check ✅ Passed The description includes a high-level summary explaining the feature, links to related SDK changes, provides specific examples, and includes testing instructions with checkboxes.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/sell-buy-2

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

cloudflare-workers-and-pages Bot commented Jun 9, 2026

Copy link
Copy Markdown

Deploying swap-dev with  Cloudflare Pages  Cloudflare Pages

Latest commit: b5fc9c3
Status: ✅  Deploy successful!
Preview URL: https://83478759.swap-dev-5u6.pages.dev
Branch Preview URL: https://feat-sell-buy-2.swap-dev-5u6.pages.dev

View logs

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 9, 2026

Copy link
Copy Markdown

Deploying explorer-dev with  Cloudflare Pages  Cloudflare Pages

Latest commit: b5fc9c3
Status: ✅  Deploy successful!
Preview URL: https://64b4ee53.explorer-dev-dxz.pages.dev
Branch Preview URL: https://feat-sell-buy-2.explorer-dev-dxz.pages.dev

View logs

 In tools/scripts/install.js:
  - Instead of skipping https-pinned non-SDK @cowprotocol deps, collect their name@version lockfile keys (forceResolveKeys).
  - Before the preview install, strip those entries from pnpm-lock.yaml (packages: + snapshots: blocks). pnpm then re-resolves just those packages as direct npmjs tarballs.
  - Restore the original lockfile in finally so the working tree stays clean.

  Verified: syntax check passes, version parsing returns 0.11.0, the stripper removes exactly the two cms blocks (228 bytes, 263→261 @cowprotocol keys) with no collateral, and the full strip-then-install
  flow installs cms successfully even with the GitHub scope override active.
… feat/sell-buy-2

# Conflicts:
#	apps/cowswap-frontend/package.json
#	apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormButtons/tradeButtonsMap.tsx
#	apps/explorer/package.json
#	apps/sdk-tools/package.json
#	apps/widget-configurator/package.json
#	libs/analytics/package.json
#	libs/balances-and-allowances/package.json
#	libs/common-const/package.json
#	libs/common-hooks/package.json
#	libs/common-utils/package.json
#	libs/core/package.json
#	libs/currency/package.json
#	libs/ens/package.json
#	libs/events/package.json
#	libs/multicall/package.json
#	libs/permit-utils/package.json
#	libs/tokens/package.json
#	libs/types/package.json
#	libs/ui/package.json
#	libs/wallet/package.json
#	libs/widget-lib/package.json
#	pnpm-lock.yaml
#	tools/scripts/install.js
@socket-security

socket-security Bot commented Jun 15, 2026

Copy link
Copy Markdown

@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

🤖 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 `@libs/types/package.json`:
- Around line 27-28: Update the SDK versions in the package.json dependencies
section to actual, available versions on npm. Change the `@cowprotocol/cow-sdk`
version from 9.2.0 to an existing version such as 9.0.2, and update
`@cowprotocol/sdk-bridging` version from 4.2.0 to an actual available version on
the npm registry. Verify both updated versions exist before committing to ensure
the dependencies can be properly resolved.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 515d28bc-cf4c-4647-a568-19e7d31bc56d

📥 Commits

Reviewing files that changed from the base of the PR and between c645fa1 and 5514f2e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (24)
  • apps/cowswap-frontend/package.json
  • apps/cowswap-frontend/src/locales/en-US.po
  • apps/cowswap-frontend/src/modules/hooksStore/containers/HooksStoreWidget/index.tsx
  • apps/cowswap-frontend/src/modules/tradeFormValidation/pure/QuoteApiErrorButton.pure.tsx
  • apps/cowswap-frontend/src/modules/tradeQuote/services/fetchAndProcessQuote.ts
  • apps/explorer/package.json
  • apps/sdk-tools/package.json
  • apps/widget-configurator/package.json
  • libs/analytics/package.json
  • libs/balances-and-allowances/package.json
  • libs/common-const/package.json
  • libs/common-hooks/package.json
  • libs/common-utils/package.json
  • libs/core/package.json
  • libs/currency/package.json
  • libs/ens/package.json
  • libs/events/package.json
  • libs/multicall/package.json
  • libs/permit-utils/package.json
  • libs/tokens/package.json
  • libs/types/package.json
  • libs/ui/package.json
  • libs/wallet/package.json
  • libs/widget-lib/package.json

Comment thread libs/types/package.json

@elena-zh elena-zh 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.

Hey @shoom3301 , works perfectly fine with Bungee and Near.

Some comments:

  1. Simple swaps should be working on Hooks only (you forgot to mention about it in the description)
  2. There is one trivial priority issue #6856 that would be nice to address one day
  3. and could you please check why sell is not = buy when I bridge to BTC?
Image

Thanks

@shoom3301

Copy link
Copy Markdown
Collaborator Author

@elena-zh thanks!

  1. Agree
  2. Addressed
  3. This is a special case :) Anyway, the bridge provider doesn't have WBTC on Arbitrum as an intermediate token. It has it in Mainnet, though. You can do a search for WBTC in https://1click.chaindefuser.com/v0/tokens and see which networks support it.
image

@alfetopito alfetopito left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I see the fee is returned by the backend API, so the question is for them, but anyway, I expected it to not show any fees for this type of order.

image

But if I look closely at the order, I see the issue is because we always quote native with wrapped token instead:

{"from":"0xD711bD26Bf5B153001a7C0ACcb289782b6f775e9","sellToken":"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2","buyToken":"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee","receiver":"0xD711bD26Bf5B153001a7C0ACcb289782b6f775e9","validFor":1800,"appData":"{\"appCode\":\"CoW Swap\",\"environment\":\"pr\",\"metadata\":{\"bridging\":{\"destinationChainId\":\"42161\",\"destinationTokenAddress\":\"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\",\"providerId\":\"cow-sdk://bridging/providers/bungee\"},\"hooks\":{\"post\":[{\"callData\":\"0x00\",\"dappId\":\"cow-sdk://bridging/providers\",\"gasLimit\":\"600000\",\"target\":\"0x0000000000000000000000000000000000000000\"}]},\"orderClass\":{\"orderClass\":\"market\"},\"quote\":{\"slippageBips\":247,\"smartSlippage\":true}},\"version\":\"1.15.0\"}","appDataHash":"0xe49cf30f20c51efd0bcac4ee1dbf7f113148175eb0dc23a8521c009064a50643","priceQuality":"optimal","signingScheme":"eip1271","onchainOrder":true,"verificationGasLimit":0,"kind":"sell","sellAmountBeforeFee":"1000000000000000000"}

Anyway, not related to this PR but to backend implementation instead.

Got a case which is probably the issue I mentioned in the SDK PR regarding the symbol matching: USDT (base) -> USDT0 (arb1) routes via USDC:
image

One last thing, I don't seem to be able to actually click on swap:

Screen.Recording.2026-06-15.at.17.31.06.mov

import { SELL_ETH_RESET_STATE } from '../consts'

export function useOnCurrencySelection(): (field: Field, currency: Currency | null) => void {
export function useOnCurrencySelection(enableSellEqBuy = false): (field: Field, currency: Currency | null) => void {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I didn't get why we want to enable sell=buy conditional to whether hook store is enabled

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