Skip to content

feat(card): migrate card on-chain checks to CardController#28291

Merged
Brunonascdev merged 52 commits intomainfrom
feat/migrate-unauthenticated-state-card
Apr 6, 2026
Merged

feat(card): migrate card on-chain checks to CardController#28291
Brunonascdev merged 52 commits intomainfrom
feat/migrate-unauthenticated-state-card

Conversation

@Brunonascdev
Copy link
Copy Markdown
Contributor

@Brunonascdev Brunonascdev commented Apr 1, 2026

Description

Migrates Card authentication and region state from Redux and ad hoc hooks into CardController, and wires the Card SDK and screens to controller-backed selectors (app/selectors/cardController.ts). This follows earlier Card work already on main (feature-flag cleanup, waitlist modal, etc.) and focuses on unauthenticated/authenticated state living in the Engine controller instead of the card Redux slice.

Why: A single source of truth in CardController avoids duplicated session/cardholder logic, keeps logout and location updates consistent with provider APIs, and simplifies the Card SDK surface (no global CardVerification side-effect component).

What changed (vs origin/maingit diff origin/main...HEAD):

  • CardController
    • Owns persisted isAuthenticated, selectedCountry, activeProviderId, cardholderAccounts, and per-provider providerData (including user location for selectors).
    • Logout and user location updates go through Engine.context.CardController (e.g. logout(), setUserLocation()) instead of Redux-only flows.
    • Expanded tests in CardController.test.ts; messenger wiring in card-controller-messenger.
  • Selectors
    • Adds/uses selectIsCardAuthenticated, selectCardUserLocation, selectCardholderAccounts, selectIsCardholder, etc., in app/selectors/cardController.ts (+ cardController.test.ts).
  • Redux card slice
    • Removes authenticated/user-location fields and related actions (slice now centers on onboarding IDs, hasViewedCardButton, isDaimoDemo); large trim in index.test.ts.
  • Card SDK (app/components/UI/Card/sdk/index.tsx)
    • Reads user location from selectCardUserLocation (controller).
    • Logout calls CardController.logout(); clears queries/onboarding without resetAuthenticatedData.
    • Removes the exported CardVerification component that mounted useCardholderCheck + useCardAuthenticationVerification.
  • Removed / inlined paths
    • Deletes useCardholderCheck, getCardholder, handleLocalAuthentication (and their tests).
    • useCardAuthenticationVerification removed as a standalone flow aligned with the old pattern (files touched in diff).
  • UI & flows
    • CardHome, CardWelcome, CardAuthentication, onboarding (SignUp, PhysicalAddress, SetPhoneNumber), CardButton, AssetSelectionBottomSheet, routes, and push provisioning hooks updated to use controller-backed auth/location and tests adjusted.
    • EarnRewardsPreview: fix so UK users see the Card banner as intended (+ tests).
  • Deeplinks
    • handleCardHome, handleCardKycNotification, handleCardOnboarding simplified/aligned with controller-driven state (tests updated).
  • Navigation
    • app/components/Nav/Main/index.js adjusted for Card entry behavior.
  • Fixtures
    • tests/framework/fixtures/json/default-fixture.json updated for Card controller state.

Changelog

CHANGELOG entry: Card authentication, user location, and cardholder membership are sourced from CardController and selectIsCardAuthenticated / related selectors instead of Redux Card auth fields; global Card verification helpers and legacy auth utilities are removed in favor of controller APIs.

Related issues

Fixes:

Manual testing steps

Feature: Card controller auth and location

  Scenario: Card session reflects controller state
    Given I use Card with a provider account
    When I sign in, sign out, or cold-start the app
    Then authenticated state and region/location behavior match expectations without relying on removed Redux auth fields

  Scenario: Logout
    When I log out from Card
    Then provider logout runs via CardController, queries clear, and onboarding-related Redux resets without leaving stale auth flags

  Scenario: Rewards / UK banner
    Given a UK-eligible account context
    When I open Earn rewards preview
    Then the Card promotional banner appears as intended

  Scenario: Deeplinks
    When I open Card-related deeplinks (home, KYC notification, onboarding)
    Then navigation and handlers complete without errors after the controller migration

Screenshots/Recordings

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
Medium risk because it re-routes card authentication, user location, logout, and route-guard logic away from Redux into Engine.context.CardController, which can affect session state, navigation, and provisioning behavior if controller state is out of sync.

Overview
Migrates Card auth/location and cardholder checks from the card Redux slice + side-effect hooks to controller-backed state. Screens, hooks, deeplink handlers, and route guards now read selectIsCardAuthenticated/selectCardUserLocation/cardholder selectors from selectors/cardController.ts, and update location/auth via Engine.context.CardController APIs.

Simplifies session lifecycle and cleanup flows. CardSDKProvider logout now calls CardController.logout() and clears queries/onboarding state without resetAuthenticatedData; login/onboarding steps and CardHome auth-error handling now call CardController.validateAndRefreshSession() after token changes to sync controller auth state. Several legacy utilities/hooks (useCardholderCheck, useCardAuthenticationVerification, getCardholder, handleLocalAuthentication) and the global CardVerification component are removed, with tests/snapshots updated accordingly.

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

Brunonascdev and others added 30 commits March 20, 2026 12:43
…/metamask-mobile into feat/card-feature-flag-refactor
@github-actions github-actions bot added risk-high Extensive testing required · High bug introduction risk and removed risk-high Extensive testing required · High bug introduction risk labels Apr 4, 2026
@github-actions github-actions bot added risk-medium Moderate testing recommended · Possible bug introduction risk and removed risk-high Extensive testing required · High bug introduction risk labels Apr 4, 2026
@github-actions github-actions bot added risk-high Extensive testing required · High bug introduction risk and removed risk-medium Moderate testing recommended · Possible bug introduction risk labels Apr 4, 2026
Copy link
Copy Markdown

@cursor cursor bot left a comment

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 0d0b9b2. Configure here.

@github-actions github-actions bot added risk-high Extensive testing required · High bug introduction risk and removed risk-high Extensive testing required · High bug introduction risk labels Apr 6, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

🔍 Smart E2E Test Selection

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

E2E Test Selection:
This PR makes significant architectural changes to the MetaMask Card feature:

  1. CardController refactoring (HIGH RISK): The cardholder check logic has been moved from Redux thunks/hooks into the CardController itself. The controller now subscribes to KeyringController:unlock and AccountTreeController:stateChange events. This is a core controller change that affects how card authentication and cardholder status are determined.

  2. Redux slice cleanup: Removed cardholderAccounts, isAuthenticated, userCardLocation, isLoaded from the Redux card slice. These are now managed by the CardController state. This is a breaking change to the state shape.

  3. Selector migration: Selectors moved from Redux slice to cardController.ts - selectIsCardholder, selectHasCardholderAccounts, selectIsCardAuthenticated, selectCardUserLocation. Multiple components updated to use new selectors.

  4. Navigation change: CardVerification component removed from Main/index.js - this was a side-effect component that ran useCardholderCheck and useCardAuthenticationVerification. These are now handled by controller events.

  5. Default fixture change: default-fixture.json updated to remove isAuthenticated and userCardLocation fields - this directly impacts E2E test fixtures.

  6. Deep link handlers: All three card deep link handlers updated to use new selectors.

  7. EarnRewardsPreview: Updated to use new selectors from cardController.

SmokeCard is the primary tag - directly tests Card home screen, Add Funds, Advanced Card Management, Card navbar button, and card analytics. All of these are affected by the authentication state changes, cardholder detection refactoring, and selector migrations.

SmokeTrade is required per SmokeCard tag description (Add Funds uses swaps). Also, the EarnRewardsPreview component (part of Rewards/Earn) uses the updated card selectors.

SmokeConfirmations is required per SmokeCard tag description (Add Funds uses swaps which require transaction confirmations).

The default-fixture.json change (removing isAuthenticated and userCardLocation) could affect any E2E test that relies on this fixture, but since these fields were Card-specific, the impact should be limited to Card-related tests.

Performance Test Selection:
The changes are focused on architectural refactoring of the Card feature - moving state management from Redux to the CardController. While there are controller event subscriptions added (KeyringController:unlock, AccountTreeController:stateChange), these are debounced (50ms) and only affect the Card feature. There are no changes to UI rendering performance, list rendering, animations, account/network list components, or critical user flows like login, balance loading, or app startup that would warrant performance testing.

View GitHub Actions results

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

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

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 6, 2026

Quality Gate Failed Quality Gate failed

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

See analysis details on SonarQube Cloud

@Brunonascdev Brunonascdev added the skip-sonar-cloud Only used for bypassing sonar cloud when failures are not relevant to the changes. label Apr 6, 2026
Copy link
Copy Markdown
Contributor

@christopherferreira9 christopherferreira9 left a comment

Choose a reason for hiding this comment

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

Looks good for QA

@Brunonascdev Brunonascdev added this pull request to the merge queue Apr 6, 2026
Merged via the queue into main with commit 853bcfb Apr 6, 2026
137 of 144 checks passed
@Brunonascdev Brunonascdev deleted the feat/migrate-unauthenticated-state-card branch April 6, 2026 14:04
@github-actions github-actions bot locked and limited conversation to collaborators Apr 6, 2026
@metamaskbot metamaskbot added the release-7.74.0 Issue or pull request that will be included in release 7.74.0 label Apr 6, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.74.0 Issue or pull request that will be included in release 7.74.0 risk-high Extensive testing required · High bug introduction risk size-XL skip-sonar-cloud Only used for bypassing sonar cloud when failures are not relevant to the changes. team-card Card Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants