Skip to content

feat(card): refactor spending limit screen#27918

Merged
Brunonascdev merged 4 commits into
mainfrom
feat/card-asset-sorting
Mar 26, 2026
Merged

feat(card): refactor spending limit screen#27918
Brunonascdev merged 4 commits into
mainfrom
feat/card-asset-sorting

Conversation

@Brunonascdev

@Brunonascdev Brunonascdev commented Mar 25, 2026

Copy link
Copy Markdown
Contributor

Description

Refactors the Card Spending limit screen and related asset selection so default token choice and list ordering follow wallet fiat value for the currently selected MetaMask account, replaces the multi–quick-select asset row with a settings-style summary card, and moves full vs. restricted limit + amount into a dedicated bottom sheet.

Why: Quick-select assumed fixed symbols (e.g. mUSD-first) and did not consistently reflect real balances or account switches. Asset lists should align with how much the user actually holds per account, and the main screen should read like compact “settings” rows instead of several tappable asset tiles.

What changed:

  • constants.ts: Adds CARD_CHAIN_IDS (Linea, Base, Monad hex 0x8f, Solana) using @metamask/transaction-controller chain IDs where applicable; keeps caipChainIdToNetwork derived from cardNetworkInfos.
  • useSpendingLimit:
    • Removes quickSelectTokens, handleQuickSelectToken, and isOtherSelected.
    • Uses useTokensWithBalance({ chainIds: CARD_CHAIN_IDS }) so default token candidates are sorted by tokenFiatAmount (highest first); if none have positive fiat, falls back to Linea mUSD when present. Candidates come from NotEnabled allowances when applicable, otherwise buildTokenListFromSettings + sdk.getSupportedTokensByChainId.
    • Resets initialization when the selected internal account changes (setHasInitialized(false), clear selection) so defaults are not stale across account switches.
    • handleAccountSelect opens the account selector; handleOtherSelect opens AssetSelectionBottomSheet with excludedTokens set to the current row token; handleLimitSelect opens the new spending-limit options sheet.
    • Consumes returnedLimitType / returnedCustomLimit from the options sheet via useFocusEffect (same pattern as token return params).
  • SpendingLimit.tsx: Setup header copy (setup_title / setup_description); settings card with three rows — Account, Token (label SYMBOL on NETWORK) with chevron → asset picker, Spending limit row → options sheet; footer Cancel / Confirm.
  • SpendingLimitOptionsSheet.tsx (new modal route): Full access vs Spending limit (with numeric input), LimitOptionItem styling tweaks (input alignment, maxLength={12}), confirm navigates back with limit params.
  • Routes / Card stack: Registers CARD.MODALS.SPENDING_LIMIT_OPTIONS for the options sheet.
  • AssetSelectionBottomSheet: Optional excludedTokens in navigation params to hide the token already shown on the spending-limit Token row; NotEnabled tokens are sorted by fiat using rawFiatNumber on enriched rows.
  • useAssetBalances: Uses CARD_CHAIN_IDS for useTokensWithBalance (adds Monad, aligns with card networks); exposes rawFiatNumber on AssetBalanceInfo for sorting.
  • AssetCard: caipChainId support and optional onPress — token icon and network badge use the token’s real chain, not Linea-only.
  • locales/languages/en.json: New/updated card.card_spending_limit strings (setup_title, setup_description, account_label, token_label, copy tweaks; Restricted label renamed to Spending limit where used).
  • Tests: useSpendingLimit.test.ts, SpendingLimit.test.tsx, AssetSelectionBottomSheet.test.tsx updated for new hooks, navigation params, and UI structure.

Changelog

CHANGELOG entry: Card spending limit screen uses account-scoped wallet fiat to pick and order default tokens; main view is a settings card (account, token, limit) with asset sheet exclusions and fiat sort for NotEnabled tokens; full vs restricted limit is configured in a dedicated bottom sheet.

Related issues

Fixes:

Manual testing steps

Feature: Card spending limit and asset list reflect wallet value

  Scenario: Default token on spending limit after open
    Given I have multiple Card-supported tokens with different fiat balances on the selected account
    When I open Spending Limit (manage / enable / onboarding as applicable)
    Then the pre-selected token favors the highest fiat balance, or Linea mUSD when no positive fiat

  Scenario: Switch account
    Given I change the active MetaMask account from the Account row
    When I return to or remain on Spending Limit
    Then default token selection reflects the new account’s balances (not a stale selection)

  Scenario: Token row → asset sheet
    When I tap the Token row and pick another asset
    Then the row updates and the previously selected token is not duplicated in the list when excluded

  Scenario: Spending limit row → options sheet
    When I tap the Spending limit row
    Then I can choose full access or enter a restricted amount, confirm, and see the summary row update

  Scenario: Asset selection list ordering
    Given tokens in NotEnabled state appear in the asset sheet
    When I view the list
    Then NotEnabled tokens are ordered by fiat value where implemented

Screenshots/Recordings

Simulator.Screen.Recording.-.iPhone.17.-.2026-03-25.at.22.58.19.mov

Pre-merge author checklist

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

Medium Risk
Refactors card spending-limit UX and selection logic, adding new modal navigation and changing default token selection/sorting based on wallet fiat balances; regressions could affect which token/limit a user configures or sees by default, especially across account switches.

Overview
Refactors the Card Spending Limit flow into a settings-style screen with Account, Token, and Spending limit rows, replacing the prior quick-select token tiles and in-place limit options.

Adds a new SpendingLimitOptionsSheet modal to configure full vs restricted limits (with sanitized/max-length input) and returns values via route params; useSpendingLimit now drives navigation to the account selector, token picker (excluding the currently selected token), and the new limit sheet, and resets selection when the active internal account changes.

Updates AssetSelectionBottomSheet to support excludedTokens and to sort NotEnabled tokens by wallet fiat value (via rawFiatNumber from useAssetBalances), standardizes supported card chain IDs via CARD_CHAIN_IDS, and refreshes related strings/tests.

Written by Cursor Bugbot for commit 68e7178. This will update automatically on new commits. Configure here.

@Brunonascdev Brunonascdev self-assigned this Mar 25, 2026
@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.

@metamaskbot metamaskbot added the team-card Card Team label Mar 25, 2026
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.92593% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.56%. Comparing base (9564fd6) to head (d54927b).
⚠️ Report is 36 commits behind head on main.

Files with missing lines Patch % Lines
app/components/UI/Card/hooks/useSpendingLimit.ts 71.42% 0 Missing and 6 partials ⚠️
...ents/UI/Card/Views/SpendingLimit/SpendingLimit.tsx 55.55% 1 Missing and 3 partials ⚠️
...SelectionBottomSheet/AssetSelectionBottomSheet.tsx 83.33% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #27918      +/-   ##
==========================================
+ Coverage   82.52%   82.56%   +0.04%     
==========================================
  Files        4800     4828      +28     
  Lines      123748   124025     +277     
  Branches    27576    27644      +68     
==========================================
+ Hits       102122   102405     +283     
+ Misses      14567    14565       -2     
+ Partials     7059     7055       -4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Brunonascdev Brunonascdev marked this pull request as ready for review March 25, 2026 17:51
@Brunonascdev Brunonascdev requested a review from a team as a code owner March 25, 2026 17:51
Comment thread app/components/UI/Card/Views/SpendingLimit/SpendingLimit.test.tsx
Comment thread app/components/UI/Card/Views/SpendingLimit/SpendingLimit.tsx Outdated
@github-actions github-actions Bot added size-XL risk-medium Moderate testing recommended · Possible bug introduction risk and removed size-L labels Mar 26, 2026
Comment thread app/components/UI/Card/constants.ts Outdated
Comment thread locales/languages/en.json Outdated
@github-actions github-actions Bot added risk-medium Moderate testing recommended · Possible bug introduction risk and removed risk-medium Moderate testing recommended · Possible bug introduction risk labels Mar 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

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

E2E Test Selection:
All changes are contained within the MetaMask Card feature (app/components/UI/Card/). The PR is a significant UI/UX refactor of the SpendingLimit screen and its supporting hooks/components:

  1. SpendingLimit.tsx - Major redesign: replaced quick-select asset cards with a settings-card style layout featuring Account, Token, and Spending Limit rows with navigation to sub-screens
  2. SpendingLimitOptionsSheet.tsx - New bottom sheet modal for limit type selection (full/restricted) with custom amount input
  3. Routes.ts - New SPENDING_LIMIT_OPTIONS route added to Card modals navigation
  4. useSpendingLimit.ts - Significant hook refactor: removed quickSelectTokens/isOtherSelected, added handleAccountSelect/handleLimitSelect, integrated account switching detection, improved token initialization with wallet balance sorting
  5. AssetSelectionBottomSheet.tsx - Added excludedTokens support and improved fiat-based sorting
  6. useAssetBalances.tsx - Refactored to use CARD_CHAIN_IDS constant
  7. constants.ts - Added CARD_CHAIN_IDS export, refactored caipChainIdToNetwork
  8. sanitizeCustomLimit.ts - New utility extracted from hook
  9. locales/en.json - New string keys for account/token labels

Primary tag: SmokeCard (directly tests Card integration features including spending limit flows).
Dependent tags per SmokeCard description: SmokeTrade (Add Funds uses swaps) and SmokeConfirmations (Add Funds uses transaction confirmations).

The changes do not touch shared navigation infrastructure, Engine, controllers, or other feature areas, so other tags are not warranted.

Performance Test Selection:
Changes are confined to the Card feature's SpendingLimit UI and hooks. No performance-sensitive areas are affected: no account list rendering, no app startup/initialization, no login flows, no swap quote fetching performance, no asset loading list rendering changes that would impact performance benchmarks. The UI refactor is a layout change within a Card-specific screen, not a broadly-used component.

View GitHub Actions results

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

Comment thread app/components/UI/Card/hooks/useSpendingLimit.ts
@github-actions

Copy link
Copy Markdown
Contributor

E2E Fixture Validation — Schema is up to date
17 value mismatches detected (expected — fixture represents an existing user).
View details

@sonarqubecloud

Copy link
Copy Markdown

@Brunonascdev Brunonascdev added this pull request to the merge queue Mar 26, 2026
Merged via the queue into main with commit de36dee Mar 26, 2026
95 of 96 checks passed
@Brunonascdev Brunonascdev deleted the feat/card-asset-sorting branch March 26, 2026 11:28
@github-actions github-actions Bot locked and limited conversation to collaborators Mar 26, 2026
@metamaskbot metamaskbot added the release-7.72.0 Issue or pull request that will be included in release 7.72.0 label Mar 26, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.72.0 Issue or pull request that will be included in release 7.72.0 risk-medium Moderate testing recommended · Possible bug introduction risk size-XL team-card Card Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants