Skip to content

fix(quick-buy): show all held tokens in Pay with and split Pay with/Receive flows#31195

Merged
xavier-brochard merged 5 commits into
mainfrom
fix/quickbuy-pay-with-held-tokens
Jun 8, 2026
Merged

fix(quick-buy): show all held tokens in Pay with and split Pay with/Receive flows#31195
xavier-brochard merged 5 commits into
mainfrom
fix/quickbuy-pay-with-held-tokens

Conversation

@xavier-brochard

@xavier-brochard xavier-brochard commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Description

In the QuickBuy bottom sheet, the Pay with picker only listed a curated allowlist of native tokens and stablecoins. Tokens the user actually held (e.g. CAKE, UP, dogwifhat) were missing, so they couldn't pay with them.

This PR:

  1. Fixes the missing tokens bug. usePayWithTokens now sources every tradable token the user holds across the bridge-enabled source chains (same useTokensWithBalance source the Bridge/Swap pickers use), instead of a hardcoded candidate list.
  2. Cleanly splits the two flows. The previously combined screen branched internally on tradeMode. It is now split into QuickBuyPayWithScreen (buy / "Pay with") and QuickBuyReceiveScreen (sell / "Receive"), both rendering a shared presentational QuickBuyTokenSelectList, routed by a small QuickBuyTokenSelectScreen dispatcher.
  3. Extracts shared logic. Token balance/fiat/exchange-rate enrichment moved into a pure enrichTokenBalance helper reused by both the "Pay with" and "Receive" hooks, plus a shared tokenKey util.
  4. Fixes fiat display for non-USD users. QuickBuy is USD-first (currencyExchangeRate is USD-per-token and the amount entry renders $). The balance fiat was computed from usdConversionRate but formatted with the user's selected currency, mislabeling a USD value as e.g. €2000.00. Fiat fields are now formatted as USD to match the value and the rest of the flow.

Changelog

CHANGELOG entry: Fixed QuickBuy "Pay with" not showing all tokens the user holds, and corrected the fiat amount currency shown for non-USD users.

Related issues

Fixes: TSA-609

Manual testing steps

Feature: QuickBuy Pay with held tokens

  Scenario: user pays with an arbitrary held token
    Given I hold tokens that are not stablecoins or natives (e.g. CAKE, UP, dogwifhat)
    When I open the QuickBuy bottom sheet and tap "Pay with"
    Then I see all of my held, tradable tokens listed
    And I can select one and continue to the amount screen

  Scenario: user on a non-USD currency sees correct fiat
    Given my display currency is set to EUR
    When I open the "Pay with" picker
    Then each token's fiat value is shown in USD ($), matching the amount screen

  Scenario: user selling a position picks a stablecoin to receive
    Given I open QuickBuy in sell mode
    When I tap "Receive"
    Then I see the stablecoin options with the position chain offered first

Screenshots/Recordings

Before

image

After

image

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
    • Ideally on a mid-range device; emulator is acceptable
  • I've tested with a power user scenario
    • Use these power-user SRPs to import wallets with many accounts and tokens
  • I've instrumented key operations with Sentry traces for production performance metrics

For performance guidelines and tooling, see the Performance Guide.

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Made with Cursor


Note

Medium Risk
Changes which tokens can fund trades and how USD rates are computed for amount entry; sell receive stables behavior is preserved but enrichment rules (no stable $1 fallback on Pay with) differ from the old hook.

Overview
Fixes QuickBuy Pay with so users see all held, tradable tokens (via Bridge’s useTokensWithBalance) instead of a hardcoded native/stable allowlist, with strict pricing so only tokens with a resolvable USD rate appear.

Pay with and Receive are split: buy uses QuickBuyPayWithScreen, sell uses QuickBuyReceiveScreen, both backed by shared QuickBuyTokenSelectList and routed by QuickBuyTokenSelectScreen on the existing payWith screen.

Token balance/fiat/exchange-rate logic moves into pure enrichTokenBalance (used by new usePayWithTokens and useReceiveTokens); sourceTokenCandidates / useSourceTokenOptions are removed. Fiat labels in the picker are formatted as USD to match QuickBuy’s USD-first amount flow (fixes wrong currency symbol for non-USD display settings).

Reviewed by Cursor Bugbot for commit f31322e. Bugbot is set up for automated code reviews on this repo. Configure here.

…eceive flows

The "Pay with" picker only offered a curated stablecoin/native allowlist, so
held tokens like CAKE, UP and dogwifhat were missing. It now sources every
tradable token the user holds across the bridge-enabled source chains.

Also splits the previously combined screen into clearly separated "Pay with"
(buy) and "Receive" (sell) flows over a shared presentational list, extracts a
reusable `enrichTokenBalance` helper and `tokenKey` util, and fixes fiat
display: balances are USD-denominated so they are now formatted as USD instead
of being mislabeled with the user's selected currency symbol.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@mm-token-exchange-service mm-token-exchange-service Bot added team-social-ai Social & AI team INVALID-PR-TEMPLATE PR's body doesn't match template labels Jun 8, 2026
Auto-formatter import ordering only; no logic changes.

Co-authored-by: Cursor <cursoragent@cursor.com>
@mm-token-exchange-service mm-token-exchange-service Bot removed the INVALID-PR-TEMPLATE PR's body doesn't match template label Jun 8, 2026
@xavier-brochard xavier-brochard marked this pull request as ready for review June 8, 2026 10:34
@github-actions github-actions Bot added the risk:low AI analysis: low risk label Jun 8, 2026
Introduces a new utility function `isStablecoinSymbol` to validate stablecoin symbols, ensuring case-insensitive matching. This functionality is integrated into the `usePayWithTokens` and `useReceiveTokens` hooks to apply a $1 fallback rate for stablecoins only. Additionally, comprehensive tests for the stablecoin validation logic have been added to ensure accuracy and reliability.
@github-actions github-actions Bot added risk:medium AI analysis: medium risk and removed risk:low AI analysis: low risk labels Jun 8, 2026
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokePerps, SmokeSwap, SmokeConfirmations, SmokeWalletPlatform
  • Selected Performance tags: None (no tests recommended)
  • Risk Level: medium
  • AI Confidence: 72%
click to see 🤖 AI reasoning details

E2E Test Selection:
The PR refactors the QuickBuy feature within SocialLeaderboard/TraderPositionView. Key changes:

  1. Functional change in token source: usePayWithTokens now uses useTokensWithBalance (actual held tokens across bridge-enabled chains) instead of a static candidate list. This changes which tokens appear in the "Pay with" picker.

  2. New screen separation: QuickBuyTokenSelectScreen now routes to separate QuickBuyPayWithScreen (buy mode) and QuickBuyReceiveScreen (sell mode) instead of a single combined screen.

  3. Extracted utilities: enrichTokenBalance, stablecoins, tokenKey are new pure utility modules extracted from the deleted sourceTokenCandidates.ts and useSourceTokenOptions.ts.

SmokePerps: Directly relevant - the Perps Add Funds flow uses QuickBuy for token selection. The changed hooks (usePayWithTokens, useReceiveTokens) power the token picker in the QuickBuy bottom sheet used in Perps flows.

SmokeSwap: Relevant because QuickBuy uses bridge/swap infrastructure (useTokensWithBalance, BridgeToken types, bridge selectors). Changes to token selection logic could affect swap-related flows.

SmokeConfirmations: Required per SmokePerps tag description - "Add Funds deposits are on-chain transactions" that go through confirmations.

SmokeWalletPlatform: Required per SmokePerps tag description - "Perps is also a section inside the Trending tab (SmokeWalletPlatform)".

No E2E spec files directly test QuickBuy/SocialLeaderboard, so the risk is medium - the changes are internal refactoring with a meaningful behavioral change in token sourcing. Confidence is moderate because no direct E2E tests exist for this feature path.

Performance Test Selection:
The changes are scoped to the QuickBuy bottom sheet within the SocialLeaderboard/TraderPositionView. While usePayWithTokens now uses useTokensWithBalance (which queries across multiple chains), this is only triggered when the QuickBuy sheet opens - not during core wallet rendering, account list display, login, or app launch. The performance impact is isolated to a specific user interaction flow that is not covered by the available performance test tags (@PerformanceAccountList, @PerformanceOnboarding, @PerformanceLogin, @PerformanceSwaps, @PerformanceLaunch, @PerformanceAssetLoading, @PerformancePredict, @PerformancePreps).

View GitHub Actions results

@xavier-brochard xavier-brochard added the skip-e2e skip E2E test jobs label Jun 8, 2026
Refactors the `enrichTokenBalance` function to remove the fallback exchange rate option, streamlining the handling of tokens without market prices. Updates tests to reflect the new behavior, ensuring that tokens with no resolvable price return null or a zero balance as appropriate. Adjusts related tests in `usePayWithTokens` and `useReceiveTokens` to align with the changes in token enrichment logic.
…iceable tokens

Adds new test cases to the `enrichTokenBalance` function to verify that it correctly handles unheld tokens by returning a zero balance when lenient, and retains the actual balance for held but unpriceable tokens. Updates existing test descriptions for clarity and consistency. This ensures comprehensive coverage of token enrichment scenarios.

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit f31322e. Configure here.

// Scope holdings to networks the user has enabled in wallet settings.
if (!isChainEnabled(token.chainId)) continue;
const enrichment = enrichTokenBalance(token, deps);
if (!enrichment) continue;

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.

Pay-with list vs balance account

Medium Severity

usePayWithTokens builds the picker from useTokensWithBalance (account-group EOA and selectAccountTokensAcrossChainsForAddress), but enrichTokenBalance reads balances using selectSelectedInternalAccountByScope(EVM_SCOPE). When those addresses differ, held tokens can be dropped or priced from the wrong wallet despite appearing in the Bridge token list.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f31322e. Configure here.

@xavier-brochard xavier-brochard added this pull request to the merge queue Jun 8, 2026
Merged via the queue into main with commit 24729e4 Jun 8, 2026
103 of 106 checks passed
@xavier-brochard xavier-brochard deleted the fix/quickbuy-pay-with-held-tokens branch June 8, 2026 15:38
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 8, 2026
@metamaskbotv2 metamaskbotv2 Bot added the release-7.82.0 Issue or pull request that will be included in release 7.82.0 label Jun 8, 2026
@xavier-brochard xavier-brochard changed the title fix(quick-buy): show all held tokens in Pay with and split Pay with/Receive flows fix(quick-buy): cp-7.81.0 show all held tokens in Pay with and split Pay with/Receive flows Jun 8, 2026
@xavier-brochard xavier-brochard changed the title fix(quick-buy): cp-7.81.0 show all held tokens in Pay with and split Pay with/Receive flows fix(quick-buy): show all held tokens in Pay with and split Pay with/Receive flows Jun 8, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.82.0 Issue or pull request that will be included in release 7.82.0 risk:medium AI analysis: medium risk size-XL skip-e2e skip E2E test jobs team-social-ai Social & AI team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants