Skip to content

fix(card): missing tokens#30028

Draft
klejeune wants to merge 1 commit into
mainfrom
fix/card-missing-tokens
Draft

fix(card): missing tokens#30028
klejeune wants to merge 1 commit into
mainfrom
fix/card-missing-tokens

Conversation

@klejeune

@klejeune klejeune commented May 12, 2026

Copy link
Copy Markdown
Contributor

Description

Changelog

CHANGELOG entry:

Related issues

Fixes: card missing tokens

Manual testing steps

Feature: my feature name

  Scenario: user revokes delegation
    Given a Card token was previously delegated to

    When user revokes the delegation using revoke.cash
    Then the token is displayed as "Not enabled"

Screenshots/Recordings

Before

After

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.

@github-actions

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.

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

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

E2E Test Selection:
The changes are focused on the MetaMask Card feature:

  1. BaanxProvider.ts - buildSupportedTokens() now accepts currentWalletAddress and adds a fallback to show tokens from the feature flag even when delegationSettings is empty/null. This changes how available funding tokens are built and displayed in the Card UI. The getCardHomeData() method now passes the wallet address through.

  2. cardController.ts selector - selectCardAvailableTokens now filters Inactive tokens by the currently selected EVM account address to avoid duplicate "not enabled" rows in multi-account scenarios. Active/Limited tokens always show regardless of account.

These changes directly affect the Card Home screen's "Add Funds" flow - specifically which tokens appear as available for funding. The selectCardAvailableTokens selector feeds into useCardHomeData.tsCardHome.tsx.

SmokeMoney is the primary tag as it covers Card home screen, Add Funds flows, and card analytics. Per the SmokeMoney tag description, when Card Add Funds or similar flows execute swaps, SmokeSwap and SmokeConfirmations should also be selected. The changes don't affect ramps, browser, accounts, network management, or other unrelated areas.

Performance Test Selection:
The changes are logic/filtering changes in the Card provider and selector layer. While the selector now does additional filtering, it's a simple array filter operation that won't meaningfully impact rendering performance. No UI rendering components, list rendering, animations, or critical performance paths are changed. Performance tests are not warranted.

View GitHub Actions results

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
79.7% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

iamrestrepo pushed a commit to iamrestrepo/metamask-mobile that referenced this pull request May 20, 2026
…MetaMask#30414)

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

After switching the selected EVM account, the Spending Limit screen's
**Token** selector rendered the "No tokens available" empty state, even
when the new account had supported tokens that could be enabled. The
root cause was introduced in MetaMask#30028:
`BaanxProvider.buildSupportedTokens` synthesized the "Not enabled"
placeholder rows once at fetch time and stamped them with the account
that was selected during the fetch. `cardHomeData` is not refetched on a
plain account switch, so the stale `walletAddress` on those placeholders
no longer matched the new selected account and the downstream filter in
`selectCardAvailableTokens` removed them all.

Rather than triggering a network refetch on every account change (the
`getCardHomeData` call is heavy), this PR moves the placeholder
synthesis into the selector layer so the list is recomputed reactively
from data that is already in the store.

- `BaanxProvider.buildSupportedTokens` no longer creates inactive
placeholders or takes a `currentWalletAddress`. Its sole responsibility
is now to enrich the real `fundingAssets` with the matching
`delegationContract` from `delegationSettings`.
- `selectCardAvailableTokens` now combines `cardHomeData`, the selected
EVM account, and `selectCardFeatureFlag`. It returns the filtered real
entries **plus** Inactive placeholders synthesized from
`delegationSettings` via `buildDelegationTokenList`, each stamped with
the currently selected wallet address. Memoization keeps recomputation
cheap.
- `selectCardLineaUsdcToken` is rebased on `selectCardAvailableTokens`
so the Cashback screen also benefits from the synthesized USDC-on-Linea
placeholder.

No data-fetching or controller subscription is added; the selector
recomputes from already-cached state.

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: Fixed a bug where the Card spending-limit token
selector incorrectly showed "No tokens available" after switching
accounts.

## **Related issues**

Refs: MetaMask#30028

## **Manual testing steps**

```gherkin
Feature: Card spending-limit token selector reflects the selected account

  Scenario: Token list reflects the new account after switching
    Given the Card feature is enabled
      And I have at least two EVM accounts (Account A and Account B)
      And Account A has at least one Card-supported token enabled (e.g. USDC on Linea)
      And Account B has no Card token enabled yet
      And the Card spending-limit screen is open with Account A selected
      And the Token selector shows the supported tokens

    When I switch the selected account to Account B
      And I open the Token selector

    Then the Token selector lists the Card-supported tokens (e.g. USDC on Linea) as "Not enabled" for Account B
      And it does NOT show the "No tokens available" empty state
      And no Card home-data network refetch is triggered by the account switch

  Scenario: Real funding assets keep being shown alongside placeholders
    Given I have an account with at least one delegated Card token (Active)

    When I open the Card spending-limit screen for that account

    Then the Active token is shown with its enabled state
      And any other Card-supported tokens that are not yet enabled appear as "Not enabled" placeholders
      And the placeholders are stamped with the currently selected wallet address

  Scenario: Cashback Linea USDC continues to work
    Given the Card feature is enabled
      And the selected account has not yet enabled USDC on Linea

    When I open the Cashback flow

    Then USDC on Linea is detected as the cashback token (via the synthesized placeholder)
      And the "Linea funding requirement" path renders as expected
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### 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](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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.

<!-- Generated with the help of the pr-description AI skill -->

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Moves token placeholder synthesis from provider fetch-time to selector
projection-time, changing what tokens are shown and how they’re sorted
after account switches. Risk is moderate because it affects
spending-limit and cashback token selection logic across wallets but is
covered by updated tests.
> 
> **Overview**
> Fixes an account-switch bug where the spending-limit token picker
could show *no tokens available* by **moving “Not enabled” placeholder
creation out of `BaanxProvider.buildSupportedTokens` and into
`selectCardAvailableTokens`**, so placeholders are stamped with the
*currently selected* EVM wallet without refetching home data.
> 
> `BaanxProvider.buildSupportedTokens` now only enriches real
`fundingAssets` with `delegationContract`, while selectors synthesize
delegation-derived placeholders via `buildDelegationTokenList`, dedupe
against real entries for the current wallet, and apply a deterministic
sort (priority then status). `selectCardLineaUsdcToken` is updated to
fall back to the delegation-derived placeholder (for Cashback/Linea
USDC), and tests are updated/expanded to validate placeholder behavior,
account switching, and ordering.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
336c0bd. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant