Skip to content

fix(token-details): cp-7.81.0 show swap/quick buy when only viewed token held#31393

Merged
xavier-brochard merged 2 commits into
mainfrom
fix/token-details-swap-quickbuy-eligibility
Jun 9, 2026
Merged

fix(token-details): cp-7.81.0 show swap/quick buy when only viewed token held#31393
xavier-brochard merged 2 commits into
mainfrom
fix/token-details-swap-quickbuy-eligibility

Conversation

@xavier-brochard

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

Copy link
Copy Markdown
Contributor

Description

On the Token Details screen, the Swap button and the QuickBuy (lightning/flash) icon were both gated on selectHasEligibleSwapSource, which the footer called with the currently-viewed token excluded. As a result, a user whose only funded asset was the token they were viewing (e.g. holding only ETH, on the ETH page) saw neither control, and only the fiat Buy fallback was shown.

This is incorrect: the swap handler (useHandleOnSwap) already swaps the held token away when the user holds it, and QuickBuy's sell mode operates on the position token. So holding only the viewed token is a perfectly valid reason to surface Swap and QuickBuy.

The fix calls the selector with no exclusion args in useStickyTokenActions, so the viewed token counts as a fundable/swappable asset. The selector's optional excludedChainId / excludedAddress parameters are intentionally retained for any future caller that genuinely needs "any funded asset except X".

Behavioral delta: for a held token that is not fiat-buyable and with no other holdings, the Buy on-ramp fallback no longer shows; Swap is shown instead. For buyable tokens (e.g. ETH) both still show.

Changelog

CHANGELOG entry: Fixed the Swap and Quick Buy buttons not appearing on the token details screen when the only funded asset was the token being viewed.

Related issues

Fixes: Issue where the Swap button wouldn't show, preventing me from swapping a token I actually hold.

Manual testing steps

Feature: Token details trade actions for a single-asset wallet

  Scenario: User holding only the viewed token sees Swap and Quick Buy
    Given my wallet holds a positive balance of only one token (e.g. ETH)
    And I have no other funded assets
    When I open the Token Details screen for that token
    Then the Swap button is visible
    And the Quick Buy (lightning) icon is visible
    And tapping Quick Buy opens the QuickBuy sheet where I can sell the token

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.

Note

Low Risk
Localized change to swap-eligibility gating and footer visibility on Token Details; no auth, payments, or data-layer changes.

Overview
Fixes Token Details Swap and Quick Buy staying hidden when the user’s only funded asset is the token on screen.

useStickyTokenActions no longer passes the viewed token into selectHasEligibleSwapSource as an exclusion. selectHasEligibleSwapSource is simplified to a state-only check: any asset with positive fiat balance counts, including the current token, since that balance is a valid swap source.

Tests now assert the hook uses the selector without exclusions and that a single funded “viewed” token yields eligibility true. For wallets with only one non–fiat-buyable holding, the footer may show Swap instead of the Buy on-ramp fallback when swap eligibility is true.

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

The Swap button and QuickBuy flash icon were gated on
selectHasEligibleSwapSource called with the viewed token excluded, so a
user whose only funded asset was the token on screen saw neither, even
though the swap handler can swap the held token away and QuickBuy's sell
mode works on it.

Call the selector with no exclusion args so the viewed token counts. The
optional excludedChainId/excludedAddress params are kept for future reuse.

Co-authored-by: Cursor <cursoragent@cursor.com>
@xavier-brochard xavier-brochard self-assigned this Jun 9, 2026
@github-actions

github-actions Bot commented Jun 9, 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 9, 2026
@github-actions github-actions Bot added the size-S label Jun 9, 2026
@xavier-brochard xavier-brochard changed the title fix(token-details): show swap/quick buy when only viewed token held fix(token-details): cp-7.81.0 show swap/quick buy when only viewed token held Jun 9, 2026
@mm-token-exchange-service mm-token-exchange-service Bot removed the INVALID-PR-TEMPLATE PR's body doesn't match template label Jun 9, 2026
@xavier-brochard xavier-brochard marked this pull request as ready for review June 9, 2026 12:08
@xavier-brochard xavier-brochard requested a review from a team as a code owner June 9, 2026 12:08
@github-actions github-actions Bot added the risk:medium AI analysis: medium risk label Jun 9, 2026
@xavier-brochard xavier-brochard enabled auto-merge June 9, 2026 12:26
sourcePage?: string;
}) => {
const hasEligibleSwapTokens = useSelector((state: RootState) =>
selectHasEligibleSwapSource(state, token.chainId, token.address),

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.

Are we sure dropping the token from this selector is intentional?

@xavier-brochard xavier-brochard Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes it is, it's actually the core of the fix.
Passing the token.chain and token.address was excluding it from the eligible list, causing the swap button to not appear when I'm viewing it, even when I'm'owning a non-null amount of it

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.

Okay tested, I think this is a good change

  • before - we checked all possible tokens, excluding current token
  • now - we always just check if you at least have a token eligable (including current token).

What is nice is the underlying token actions for swap navigation will select the selected token as "source" token, in case you want an easy way to swap out of the token to something else.

Comment thread app/selectors/assets/assets-list.ts Outdated
Comment on lines +166 to +171
export const selectHasEligibleSwapSource = createSelector(
[
selectAssetsBySelectedAccountGroup,
(_state: RootState, excludedChainId: string | undefined) => excludedChainId,
(
_state: RootState,
_excludedChainId: string | undefined,
excludedAddress: string | undefined,
) => excludedAddress,
(_state: RootState, excludedChainId?: string) => excludedChainId,
(_state: RootState, _excludedChainId?: string, excludedAddress?: string) =>
excludedAddress,

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.

Quick audit, there are no other places that use this.
Lets clean up - remove the params and keep it simple :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Noted, will do. I wasn't sure whether or not to remove it.

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.

TY :)

…t coverage

This update refactors the `selectHasEligibleSwapSource` selector to streamline its logic by removing unnecessary parameters and consolidating test cases. The selector now directly checks for positive fiat balances without exclusion parameters, ensuring that the currently-viewed token is counted as a valid swap source. Additionally, the test suite has been enhanced to cover more scenarios, improving overall test coverage and clarity.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions github-actions Bot added size-M and removed size-S labels Jun 9, 2026
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

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

E2E Test Selection:
The changes simplify the selectHasEligibleSwapSource selector by removing the token exclusion logic (excludedChainId/excludedAddress parameters). Previously, the currently-viewed token was excluded from swap eligibility checks; now it counts as a valid swap source. This means the Swap button in TokenDetailsStickyFooter will now appear even when the only asset with positive fiat balance is the currently-viewed token itself.

Key impact areas:

  1. SmokeSwap: The primary affected flow - swap eligibility from token details screen is changed. The Swap button visibility logic is altered, which could affect swap initiation flows. Per tag description, SmokeConfirmations should also be selected when SmokeSwap is selected.
  2. SmokeConfirmations: Required alongside SmokeSwap per tag dependency rules (transaction confirmations are part of swap flows).
  3. SmokeWalletPlatform: Token details and asset display are core wallet platform features. The TokenDetailsStickyFooter is used in TokenDetails view, MarketInsightsView, and SecurityTrustScreen - all wallet platform surfaces.

The changes are contained to the selector and hook layer, with no changes to UI components themselves. The test files confirm the behavioral change is intentional (the currently-viewed token is now a valid swap source). Risk is medium because this changes user-visible behavior (swap button visibility) in token detail screens.

Performance Test Selection:
The changes are to a selector simplification (removing exclusion parameters) and a hook update. While selectors can affect performance, this change actually simplifies the selector (fewer parameters, simpler logic), which would not negatively impact performance. No UI rendering changes, no list rendering changes, no data loading changes. Performance tests are not warranted.

View GitHub Actions results

@xavier-brochard xavier-brochard added this pull request to the merge queue Jun 9, 2026
Merged via the queue into main with commit 5edcc2c Jun 9, 2026
119 checks passed
@xavier-brochard xavier-brochard deleted the fix/token-details-swap-quickbuy-eligibility branch June 9, 2026 14:49
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 9, 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 9, 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-M team-social-ai Social & AI team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants