Skip to content

chore: release: 7.74.0#28948

Merged
joaoloureirop merged 452 commits into
stablefrom
release/7.74.00
Apr 28, 2026
Merged

chore: release: 7.74.0#28948
joaoloureirop merged 452 commits into
stablefrom
release/7.74.00

Conversation

@chloeYue
Copy link
Copy Markdown
Contributor

@chloeYue chloeYue commented Apr 16, 2026

🚀 v7.74.0 Testing & Release Quality Process

Hi Team,
As part of our new MetaMask Release Quality Process, here’s a quick overview of the key processes, testing strategies, and milestones to ensure a smooth and high-quality deployment.


📋 Key Processes

Testing Strategy

  • Developer Teams:
    Conduct regression and exploratory testing for your functional areas, including automated and manual tests for critical workflows.
  • QA Team:
    Focus on exploratory testing across the wallet, prioritize high-impact areas, and triage any Sentry errors found during testing.
  • Customer Success Team:
    Validate new functionalities and provide feedback to support release monitoring.

GitHub Signoff

  • Each team must sign off on the Release Candidate (RC) via GitHub by the end of the validation timeline (Tuesday EOD PT).
  • Ensure all tests outlined in the Testing Plan are executed, and any identified issues are addressed.

Issue Resolution

  • Resolve all Release Blockers (Sev0 and Sev1) by Tuesday EOD PT.
  • For unresolved blockers, PRs may be reverted, or feature flags disabled to maintain release quality and timelines.

Cherry-Picking Criteria

  • Only critical fixes meeting outlined criteria will be cherry-picked.
  • Developers must ensure these fixes are thoroughly reviewed, tested, and merged by Tuesday EOD PT.

🗓️ Timeline and Milestones

  1. Today (Friday): Begin Release Candidate validation.
  2. Tuesday EOD PT: Finalize RC with all fixes and cherry-picks.
  3. Wednesday: Buffer day for final checks.
  4. Thursday: Submit release to app stores and begin rollout to 1% of users.
  5. Monday: Scale deployment to 10%.
  6. Tuesday: Full rollout to 100%.

✅ Signoff Checklist

Each team is responsible for signing off via GitHub. Use the checkbox below to track signoff completion:

Team sign-off checklist

  • Accounts Framework
  • Assets
  • Card
  • Confirmations
  • Core Extension UX
  • Core Platform
  • Design System
  • Earn
  • Engagement
  • Mobile Platform
  • Mobile UX
  • Money Movement
  • Networks
  • Onboarding
  • Perps
  • Predict
  • Rewards
  • Social AI
  • Swaps And Bridge
  • Transactions
  • Wallet Integrations

This process is a major step forward in ensuring release stability and quality. Let’s stay aligned and make this release a success! 🚀

Feel free to reach out if you have questions or need clarification.

Many thanks in advance

Reference


Note

Medium Risk
Touches release/CI automation (runner images, new composite action, smart E2E selection behavior) and Android test dependencies/Braze push handling, which can affect build stability and E2E reliability despite limited product-code changes.

Overview
Bumps the app to v7.74.0 (Android versionName/versionCode) and adds the 7.74.0 release notes + updated compare links in CHANGELOG.md.

Reworks release/CI automation: introduces a local composite action setup-e2e-env, switches most iOS jobs to Cirrus macos-runner:tahoe + Xcode 26.3, updates Smart E2E selection to skip AI and force full E2E on release/* PRs, adds new smoke suites for SmokeSeedlessOnboarding, and updates RC auto-builds to trigger whenever a release branch has an open PR and to post an AI-generated test plan (removing the old generate-rc-test-plan workflow). Also adds a temporary temp-bitrise-ios-e2e POC workflow plus a use_bitrise_runner toggle for iOS E2E jobs.

Tightens testing/tooling and ownership: bans external Jest snapshots (toMatchSnapshot()), migrates several component tests away from snapshot assertions and deletes .snap files, updates ESLint rules (including banning the JS in operator in perps/core-sync-relevant paths), adds CODEOWNERS entries for Social/AI, and adds an agent skill doc for syncing perps controller to core.

Makes a few platform/build fixes: pins/excludes Espresso deps from Detox androidTest to avoid incompatibilities, adjusts a Braze yarn patch to prevent debug deps leaking to consumers, and updates Android MainActivity/Braze config to populate push payload and allow automatic push deep link handling.

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

cryptodev-2s and others added 30 commits April 10, 2026 18:09
## **Description**

Rename the `CONTROLLER_MESSENGERS` constant to `MESSENGER_FACTORIES` to
reflect that it provides messenger factories for all messenger clients
(controllers + services).

3 files changed. **PR 2 of 4** — depends on PR 1 (#28610).
- ~~PR 1: Core type renames (`Controller` → `MessengerClient`, etc.)
(#28610)~~
- **PR 2 (this):** `CONTROLLER_MESSENGERS` → `MESSENGER_FACTORIES`
- PR 3: `initModularizedControllers` → `initMessengerClients` +
utils/Engine.ts renames
- PR 4: Property renames (`controller` → `messengerClient`,
`getController` → `getMessengerClient`) in all init files + tests

Relates to
[WPC-916](https://consensyssoftware.atlassian.net/browse/WPC-916).

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/WPC-916

## **Manual testing steps**

```gherkin
Feature: Messenger client init system

  Scenario: App builds and runs normally
    Given the app is built from this branch

    When user opens the app
    Then the app behaves identically to main (no runtime behavior change)
```

## **Screenshots/Recordings**

N/A — no UI changes.

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

## **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.

[WPC-916]:
https://consensyssoftware.atlassian.net/browse/WPC-916?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Low behavioral risk (rename-only) but touches engine initialization
typing/lookup and includes a huge `default-fixture.json` update that
could affect test expectations and increase review surface.
> 
> **Overview**
> Renames the modularized messenger lookup constant from
`CONTROLLER_MESSENGERS` to `MESSENGER_FACTORIES` and updates engine
types/utilities to reference the new name (including generic return-type
mappings used during messenger-client initialization).
> 
> Updates `tests/framework/fixtures/json/default-fixture.json`, removing
legacy `ComplianceController` fields and significantly expanding
`PerpsController` cached market/user data, plus adding a few new
persisted fields (e.g., onboarding consent backfill, rewards
`ondoCampaignActivity`, and preferences `tokenOverviewChartType`).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
cf8987a. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**
Transitioning from default settings to each individual tab is not
working correctly


https://github.com/user-attachments/assets/21b9940a-68b9-4c40-a10b-aba54b7996d7


![transition](https://github.com/user-attachments/assets/73683672-fd43-4724-92ee-95377f55ee29)



## **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: fix default settings navigation

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

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

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UI/navigation configuration change; could subtly affect
onboarding stack visuals (background/header) and transition behavior but
does not touch business logic or data handling.
> 
> **Overview**
> Fixes the broken transition from `DefaultSettings` into the individual
onboarding settings screens by moving background/header styling into
`Stack.Navigator`-level `screenOptions` for `OnboardingSuccessFlow`, and
removing per-screen overrides.
> 
> Also standardizes `OnboardingNav` card background via navigator
`screenOptions` (dropping redundant per-screen `cardStyle`) to keep
transitions visually consistent.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
25a8f51. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **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?
-->

This fixes SWAPS-4336, where swap deeplinks targeting supported but
disabled networks could fall back to the default Bridge pair and show an
unexpected network-added toast. The deeplink flow now checks swap
support first, enables already-known networks in the background,
auto-adds supported missing EVM networks from `PopularList`, and
consumes one-shot toast suppression correctly so deeplink and Bridge
token-selector adds stay silent while normal manual add/remove toasts
still behave as expected.

## **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 swap deeplinks on supported disabled networks so
the requested chain opens without an extra network-added toast.

## **Related issues**

Refs:
[SWAPS-4336](https://consensyssoftware.atlassian.net/browse/SWAPS-4336)

## **Manual testing steps**

```gherkin
Feature: open swap deeplinks on supported disabled networks

  Scenario: deeplink adds a supported disabled network without showing an add toast
    Given Sei is disabled in the wallet
    When the user opens a swap deeplink for "SEI -> USDC" on Sei
    Then Bridge opens with "SEI -> USDC" selected on Sei
    And no "network added" toast is shown

  Scenario: manual re-add still shows the add toast after deeplink suppression is consumed
    Given Sei was added by deeplink and then disabled again
    When the user adds Sei back manually
    Then a "network added" toast is shown
    When the user removes Sei again
    Then a "network removed" toast is shown

  Scenario: bridge token selection adds a missing supported network silently
    Given a supported EVM network from the Bridge token selector is disabled
    When the user selects a token on that network in Bridge
    Then the network is added in the background
    And no "network added" toast is shown
```

## **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**

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

## **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.

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


[SWAPS-4336]:
https://consensyssoftware.atlassian.net/browse/SWAPS-4336?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes deeplink-driven network enablement and auto-add behavior for
Bridge/Swaps, which can affect navigation, network configuration state,
and user-facing toasts. Risk is moderated by added unit tests, but
failures could still cause incorrect chain selection or missing/extra
notifications.
> 
> **Overview**
> Fixes swap deeplinks so supported-but-disabled (or missing)
source/dest chains are made available before `BridgeView` mounts,
instead of falling back to default params.
> 
> Adds one-shot suppression for *network-added* toasts via
`networkToastSuppression`, wires `Main`'s add/remove network toast logic
through `shouldShowNetworkListToast`, and uses the suppression when
Bridge token selection or swap deeplinks auto-add EVM networks from
`PopularList` (clearing suppression on failures).
> 
> Extends `handleSwapUrl` to verify swap support
(`ALLOWED_BRIDGE_CHAIN_IDS`), best-effort enable known chains, auto-add
supported missing EVM networks, and drop unsupported/unavailable dest
tokens; expands tests to cover these scenarios.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
b3efc14. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **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?
-->

Adds a Positions/Outcomes tab bar to the game details screen, gated
behind the `extendedSportsMarketsLeagues` feature flag per league.

**What changed:**

- **`useGameDetailsTabs` hook** — New hook that reads the
`extendedSportsMarketsLeagues` remote flag, computes tabs (Positions +
Outcomes when user has positions, Outcomes-only otherwise), manages
active tab state, and determines sticky header indices.
- **`PredictGameDetailsContent`** — Fetches positions as a single source
of truth and passes them to both the hook (for tab logic) and
`PredictGameDetailsTabsContent` (for rendering). Renders
`PredictMarketDetailsTabBar` as a direct `ScrollView` child for sticky
behavior.
- **`PredictGameDetailsTabsContent`** — New component with three
rendering paths:
  - Flag off + has positions → "Your picks" title + `PredictPicks`
  - Flag off + no positions → `null`
- Flag on + has positions → tabbed view (Positions/Outcomes tabs with
sticky header)
  - Flag on + no positions → outcomes placeholder directly (no tab bar)
- **`PredictPicks`** — Refactored to accept `positions` and
`claimablePositions` as required props instead of fetching internally.
Removed "Your picks" title (now owned by parent). Removed internal
empty-state check (parent controls visibility).
- **`PredictMarketDetailsTabBar`** — Added optional `tabTwStyle` prop to
allow consumers to override individual tab styling (game details passes
`flex-1` for 2-tab even distribution).

## **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: Added Positions and Outcomes tab bar to sports game
detail screens

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/PRED-802

## **Manual testing steps**

```gherkin
Feature: Game details Positions/Outcomes tab bar

  Scenario: User views game details with positions (flag-enabled league)
    Given the user has open positions on a game in an enabled league
    And the extendedSportsMarketsLeagues flag includes that league

    When the user navigates to the game detail screen
    Then a sticky tab bar appears below the chart with "Positions" and "Outcomes" tabs
    And the "Positions" tab is selected by default
    And the user's pick items are displayed

    When the user taps the "Outcomes" tab
    Then the outcomes placeholder is displayed

  Scenario: User views game details without positions (flag-enabled league)
    Given the user has no positions on a game in an enabled league
    And the extendedSportsMarketsLeagues flag includes that league

    When the user navigates to the game detail screen
    Then no tab bar is shown
    And the outcomes placeholder is displayed directly below the chart

  Scenario: User views game details on a non-enabled league
    Given the extendedSportsMarketsLeagues flag does not include the game's league

    When the user navigates to the game detail screen
    Then no tab bar is shown
    And if the user has positions, the "Your picks" title and pick items are displayed
    And if the user has no positions, nothing is shown below the chart

  Scenario: Tab bar stickiness
    Given the user is on a game detail screen with the tab bar visible

    When the user scrolls down past the chart
    Then the tab bar sticks to the top of the screen
    And the tab content scrolls underneath
```

## **Screenshots/Recordings**



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

### **Before**


https://github.com/user-attachments/assets/e5fec3d6-b0e7-4aa9-8910-d940b8d623a6

### **After**


https://github.com/user-attachments/assets/26ed73c2-b77b-4da0-b449-c3ddaca6726b

## **Pre-merge author checklist**

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

## **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.

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk: changes game details rendering flow and how positions
data is fetched/prop-drilled to drive tabbed UI (including sticky header
behavior), gated by a remote feature flag but still impacts a
user-facing screen.
> 
> **Overview**
> Adds a feature-flagged **Positions/Outcomes** tab experience to the
Predict game details screen, including a sticky
`PredictMarketDetailsTabBar` when the user has positions in an enabled
league and an outcomes placeholder when they don’t.
> 
> Refactors `PredictPicks` to be purely presentational by requiring
`positions`/`claimablePositions` props (no internal fetching or header),
and introduces `useGameDetailsTabs` + `PredictGameDetailsTabsContent` to
centralize tab state/visibility and conditionally render picks vs
outcomes content. Updates/expands tests accordingly and removes the
prior snapshot test.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
8bf539c. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ity via the money account homepage so that i can see card deposit and other activity (#28632)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

**Reason:** Money account users need visibility into card, deposit, and
other Money-related activity from the Money home experience, with a path
to a dedicated list for review and filtering.

**Solution:** This PR adds a **Recent activity** (or equivalent) section
on `MoneyHomeView` when there are transactions, backed by
`useMoneyAccountTransactions` and new UI (`MoneyActivityList`,
`MoneyActivityItem`). Users can open a full **Money Activity** screen
(`MoneyActivityView`) via the stack route `Routes.MONEY.ACTIVITY`, with
date-grouped sections and filters (All / Deposits / Transfers).
Transaction rows reuse and extend `MultichainTransactionListItem` for
consistent display and fiat formatting via `moneyActivityFiat` and
`useMoneyTransactionDisplayInfo`. Row and “View all” taps on activity
items still surface an **under construction** alert until detail flows
ship.

Activity data is driven by remote feature flag
`moneyActivityMockDataEnabled` (or `MM_MONEY_ACTIVITY_MOCK_DATA_ENABLED`
for local/dev); when mock data is off, lists stay empty until a
dedicated Money transactions source is wired in.

<!--
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?
-->

## **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: Added Money account activity preview on the Money home
screen and a full activity list with filters when enabled by feature
flags

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MUSD-440
Fixes: https://consensyssoftware.atlassian.net/browse/MUSD-429

## **Manual testing steps**

```gherkin
Feature: Money account activity (home and full screen)

  Background:
    Given Money home and Money activity are enabled for the build
    And remote flag moneyActivityMockDataEnabled is on (or MM_MONEY_ACTIVITY_MOCK_DATA_ENABLED=true for local QA)

  Scenario: user sees activity on Money home and opens full activity
    Given I am on the Money home screen
    And mock Money transactions are available

    Then I should see a Money activity section with recent rows
    When user taps "View all" (or the section header shortcut)
    Then I should land on the full Money Activity screen with a back affordance

  Scenario: user filters activity on the full screen
    Given I am on the full Money Activity screen

    When user selects the Deposits filter
    Then only deposit-type rows should appear
    When user selects the Transfers filter
    Then only transfer-type rows should appear
    When user selects All
    Then the full merged list should appear

  Scenario: user taps an activity row (placeholder)
    Given I am on the Money home activity section or the full Money Activity screen

    When user taps a transaction row
    Then an under construction alert should be shown
```

## **Screenshots/Recordings**

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

### **Before**

<!-- [screenshots/recordings] -->

### **After**

https://www.loom.com/share/48b54c51745d4d03947ab4a48bc0fe99

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

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

## **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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Adds new Money activity UI, navigation route, and fiat-display logic
driven by a new remote/env feature flag; while mostly additive, it
touches transaction formatting/conversion and navigation paths that
could affect Money screens.
> 
> **Overview**
> Adds a **Money Activity** experience: a recent-activity preview on
`MoneyHomeView` (with a "View all" CTA) and a new full-screen
`MoneyActivityView` that groups transactions by date and supports **All
/ Deposits / Transfers** filtering.
> 
> Introduces new shared UI + data plumbing for activity rows:
`MoneyActivityList` (5-item preview), `MoneyActivityItem` (row rendering
+ optional network badge), `useMoneyTransactionDisplayInfo` and
`moneyActivityFiat` for token/fiat line formatting, and
`moneyActivityFilters`/`activityStyles` helpers.
> 
> Wires the screen into navigation by adding `Routes.MONEY.ACTIVITY` and
registering it in the Money stack (with themed `cardStyle` background),
and gates mock activity data behind a new `moneyActivityMockDataEnabled`
remote flag (with `MM_MONEY_ACTIVITY_MOCK_DATA_ENABLED` fallback).
Includes comprehensive unit tests and new `en.json` strings for activity
and transaction labels.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
a1b8842. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…other flows cp-7.73.0 (#28685)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **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?
-->

A user reported that the "Pay with" token selector on
`PredictBuyWithAnyToken`wasn't allowing to select a different token. A
transaction is needed to that work and the current logic could pick up
pending approvals from unrelated flows (bridge, swap, send, etc.),
allowing them to select tokens from the wrong transaction context.

**Root cause:** `initPayWithAnyToken()` calls `addTransactionBatch()`
directly without first rejecting existing pending approvals — unlike the
standalone `predictDeposit` flow which goes through
`useConfirmNavigation` and rejects all unapproved transactions before
creating its own. When stale approvals existed, `useApprovalRequest()`
returned the first (wrong) approval, and `PredictPayWithRow` enabled
token selection based on a generic `transactionMeta` truthiness check.

**Fix (defense-in-depth):**

1. **`usePredictBuyActions`** — added `rejectPendingTransactions()` in
the `transitionEnd` handler before `initPayWithAnyToken()`, mirroring
the cleanup pattern from `useConfirmNavigation`.
2. **`PredictPayWithRow`** — replaced the generic `transactionMeta`
truthiness check with `hasTransactionType(transactionMeta,
[TransactionType.predictDepositAndOrder])`, so the selector only enables
for the correct transaction type.

This branch also includes prior commits that handle no-quotes blocking
alerts in the buy flow and disable the pay-with selector until
transaction metadata is ready.

## **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: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: Predict buy-with-any-token token selector isolation

  Scenario: token selector stays disabled when a non-predict approval is pending
    Given user has an unconfirmed swap or bridge transaction pending
    And user navigates to a Predict market buy screen

    When the buy screen finishes loading
    Then the "Pay with" row does not show an arrow icon
    And tapping the "Pay with" row does not open the token selection modal

  Scenario: token selector enables after deposit-and-order batch is created
    Given user has no pending transactions
    And user navigates to a Predict market buy screen

    When the buy screen finishes loading and initPayWithAnyToken completes
    Then the "Pay with" row shows the arrow icon
    And tapping the "Pay with" row opens the token selection modal

  Scenario: stale approvals are rejected on buy screen entry
    Given user has an unconfirmed transaction from another flow
    And user navigates to a Predict market buy screen

    When the screen transition completes
    Then the stale unconfirmed transaction is rejected
    And a new deposit-and-order batch is created as the only pending approval
```

## **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**

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

## **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.

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches transaction/approval handling in the Predict buy flow by
programmatically rejecting unapproved transactions and tightening when
the pay-with selector is enabled; regressions could affect in-flight
approvals or block token selection.
> 
> **Overview**
> Prevents the `PredictBuyWithAnyToken` pay-with token selector from
latching onto stale approvals from other flows.
> 
> On screen entry, `usePredictBuyActions` now rejects all `unapproved`
transactions before calling `initPayWithAnyToken`, and
`PredictPayWithRow` only enables navigation/UI affordances when the
current `transactionMeta` is a `TransactionType.predictDepositAndOrder`
(otherwise it disables press, hides the arrow, and removes the muted
background). The buy flow also propagates *blocking* pay alerts
(insufficient balance / no quotes) via `usePredictBuyInfo` into
`usePredictBuyConditions` and `usePredictBuyError` to disable placing
bets and surface the correct blocking message, with updated tests.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
69b5397. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**
Fix perps and short transition
<!--
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?
-->

## **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:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

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

### **Before**

<!-- [screenshots/recordings] -->

### **After**


https://github.com/user-attachments/assets/c922da17-10ce-4ed4-b1c0-7690cbe8471b


<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] 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).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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.

## **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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches React Navigation screen options for the perps confirmation
flow, which can affect modal presentation/transition behavior and header
visibility across routes.
> 
> **Overview**
> Adjusts the perps `RedesignedConfirmations` screen options to
explicitly return `StackNavigationOptions` and always use `presentation:
'transparentModal'`, while keeping the conditional perps header
behavior.
> 
> This is intended to fix the perps/short transition behavior by
ensuring confirmations are presented with a consistent transparent modal
configuration.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
ccdf1f4. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…27898)

## **Description**

Implements
[TAT-2761](https://consensyssoftware.atlassian.net/browse/TAT-2761):
remove the PerpsHome cold-start skeleton caused by empty controller
caches.

**What changed:**
- `PerpsAlwaysOnProvider` now owns `startMarketDataPreload()`, so
preload runs from the wallet root in both wallet layouts.
- Perps hooks seed first render from live stream snapshots before
falling back to controller cache, eliminating remount flashes for
positions, orders, account, and markets.
- `MarketDataChannel.clearCache()` now preserves valid global market
cache on account-only clears.
- `PerpsController` persists successful preload market/user snapshots to
MMKV and hydrates them synchronously on startup, including
multi-provider payloads.
- `docs/perps/perps-caching-architecture.md` updated to match the actual
disk write and hydration paths.

**Benchmark (iOS simulator, April 1 2026):**
- Clean perps disk cache → first PerpsHome market data: `3908ms`
- Same-session reopen of PerpsHome → first market data: `0ms`
- After JS reload → controller hydrated `286` markets in `9ms`, first
PerpsHome market data: `0ms`

## **Changelog**

CHANGELOG entry: Added persistent disk-backed caching for Perps so the
trading screen opens instantly without loading skeletons

## **Related issues**

Fixes:
[TAT-2761](https://consensyssoftware.atlassian.net/browse/TAT-2761)

## **Manual testing steps**

```gherkin
Feature: Perps cold-start caching

  Scenario: user opens Perps after a fresh app launch
    Given the user has previously visited the Perps trading screen
    When user relaunches the app and navigates to Perps
    Then the trading screen displays market data immediately without loading skeletons

  Scenario: user reopens Perps after JS reload
    Given the user is on the Perps trading screen
    When user triggers a JS reload and navigates back to Perps
    Then cached market data is hydrated instantly from disk
    And no skeleton loading state is shown

  Scenario: user switches accounts while on Perps
    Given the user has Perps open with cached market data
    When user switches to a different account
    Then global market cache is preserved
    And only user-specific data (positions, orders) is refreshed
```

## **Screenshots/Recordings**

### **Before**

Loading skeletons shown on every PerpsHome open (cold start and JS
reload).

### **After**

Market data renders instantly from disk cache; no skeleton flash on
reopen or JS reload.

## **Pre-merge author checklist**

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

## **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.

[TAT-2761]:
https://consensyssoftware.atlassian.net/browse/TAT-2761?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
[TAT-2761]:
https://consensyssoftware.atlassian.net/browse/TAT-2761?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because it changes Perps data seeding, cache invalidation,
and persistence behavior across app restarts and reconnects; bugs could
surface as stale/incorrect positions/markets or missing invalidations
during account/provider switches.
> 
> **Overview**
> Enables *instant Perps home rendering on cold start* by adding a
disk-backed cache layer and seeding hooks from synchronous stream
snapshots before falling back to controller preload caches.
> 
> `PerpsController` now **hydrates market/user caches from disk at
construction time** and persists successful REST preloads back to disk,
with support for aggregated multi-provider payloads and a new `skipTTL`
option to serve disk-hydrated data on first paint.
> 
> `PerpsStreamManager` adds `getSnapshot()` to channels and **persists
live market/user snapshots to disk (throttled)**, preserves global
market cache on account-only clears, and resets/invalidates disk cache
on reconnect/account/provider changes. Preload ownership moves from
`Wallet/index.tsx` to `PerpsAlwaysOnProvider`, and tests/mocks/docs are
updated accordingly.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
ed83a41. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Racitores <ramon.acitores@consensys.net>
…7.73.0 (#28622)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **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?
-->

We're experiencing an issue where the SafeAreaView top padding gets
recalculated upon component mount, which results in bad UI. This PR
reduces the blast radius of the changes by consolidating all
SafeAreaView imports to `react-native-safe-area-context`. We then create
a shim for the module, which handles applying top insets via style
instead. Changes also includes:
- Consolidate safe area context mocks in test setup file
- Remove unused safe area mocks within test files
- Update snapshots

## **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:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

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

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] 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).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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.

## **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.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches SafeAreaView usage across many screens, so incorrect
inset/edge handling could cause widespread layout regressions on
iOS/Android despite being mostly mechanical changes.
> 
> **Overview**
> Standardizes `SafeAreaView` usage by switching many components from
`react-native` to `react-native-safe-area-context` (including adding
explicit `edges` in a few places) to avoid incorrect top-inset
recalculation on mount.
> 
> Refactors navigation/header configuration for
`DeFiProtocolPositionDetails` by moving `setOptions` logic out of the
component and into `MainNavigator` options via
`getDeFiProtocolPositionDetailsNavbarOptions` (now explicitly sets
`headerShown: true`).
> 
> Cleans up tests by removing per-file safe-area mocks in favor of the
centralized jest mock in `testSetupView.js`, and updates
snapshots/expectations accordingly.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f88a0cf. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…et test (#28708)

## **Description**

Fix Prettier formatting violations and eslint errors in
`SafeAreaViewWithHookTopInset.test.tsx` introduced by #28622. These
break lint checks on any unrelated PR that touches this file.

**Changes:**
- Reformat JSX to match Prettier config
- Extract inline styles to `StyleSheet.create` to fix
`react-native/no-inline-styles`
- Replace `require()` with `jest.requireActual()` in `jest.mock` factory
to fix `@typescript-eslint/no-require-imports`

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes lint/formatting regressions from #28622

## **Manual testing steps**

```gherkin
Feature: SafeAreaViewWithHookTopInset test lint compliance

  Scenario: lint and tests pass on the test file
    Given the file app/shims/SafeAreaViewWithHookTopInset.test.tsx

    When running eslint on the file
    Then zero errors are reported

    When running jest on the file
    Then all 20 tests pass
```

## **Screenshots/Recordings**

N/A — no visual changes, formatting and lint fixes only.

### **Before**

6 eslint errors on `main`:
- 2x `@typescript-eslint/no-require-imports` — `require()` inside
`jest.mock` factory
- 4x `react-native/no-inline-styles` — inline style objects in test
assertions

### **After**

0 eslint errors, 0 eslint-disable comments, all 20 tests passing.

## **Pre-merge author checklist**

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

## **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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: changes are confined to a Jest test file and only adjust
mocks/style declarations to satisfy linting/formatting, without touching
runtime code paths.
> 
> **Overview**
> Cleans up `SafeAreaViewWithHookTopInset.test.tsx` to pass lint/format
checks by switching `jest.mock` factories from `require()` to typed
`jest.requireActual()` and tightening ref typings in the mock
`SafeAreaView`.
> 
> Replaces inline style objects used in tests with a shared
`StyleSheet.create` (`testStyles`) and applies minor Prettier-driven
JSX/line-wrap formatting changes, leaving test coverage/behavior
unchanged.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
00a20c7. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Add app lifecycle actions (`app_background`, `app_foreground`,
`app_restart`) to the agentic tooling with platform-aware
implementations (iOS `simctl` + Android `adb`). Enable multi-device CDP
target discovery so `status` probes all targets across both platforms.
Fix preflight to reuse a healthy Metro instance (curl /status check) and
warn on platform mismatch instead of failing. Add `--input key=value`
flag to `validate-recipe.js`.

Also fixes switch/end nodes bypassing `when` guards (caused TypeError on
default config), and adds automatic `run.log` capture for every recipe
execution.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: Agentic lifecycle actions and multi-device support

  Scenario: run app-lifecycle recipe in dry-run mode
    Given the agentic tooling is available

    When user runs validate-recipe with app-lifecycle.json --dry-run
    Then recipe parses and validates without errors

  Scenario: CDP bridge status shows multiple targets
    Given both iOS simulator and Android emulator are running

    When user runs cdp-bridge.js status
    Then both platform targets are listed

  Scenario: lifecycle actions execute per platform
    Given the app is running on iOS simulator

    When user triggers app_background action
    Then the app moves to background via simctl
```

## **Screenshots/Recordings**

### **Before**

N/A — new tooling feature

### **After**

- `node validate-recipe.js recipes/app-lifecycle.json --dry-run` —
parses OK
- Lifecycle actions validated on both iOS simulator and Android emulator
- Multi-device target discovery working across platforms

## **Validation Recipe**

<details><summary>app-lifecycle.json (20 nodes — short background, long
background, restart)</summary>

```json
{
  "title": "App Lifecycle — validate data survives background, long background, and restart",
  "description": "Reference recipe demonstrating three lifecycle stress levels: short background (within WS grace period), long background (exceeds grace period, forces full WS reconnection), and full app restart. Use as a template for PR recipes that need lifecycle validation.",
  "inputs": {
    "symbol": { "type": "string", "default": "BTC" },
    "short_background_ms": { "type": "number", "default": 5000 },
    "long_background_ms": { "type": "number", "default": 30000 },
    "test_short_background": { "type": "boolean", "default": true },
    "test_long_background": { "type": "boolean", "default": true },
    "test_restart": { "type": "boolean", "default": false }
  },
  "validate": {
    "workflow": {
      "pre_conditions": ["wallet.unlocked", "perps.feature_enabled"],
      "entry": "nav-market-list",
      "nodes": {
        "nav-market-list": { "action": "navigate", "target": "PerpsTrendingView", "next": "wait-markets" },
        "wait-markets": { "action": "wait_for", "assert": { "operator": "gt", "field": "count", "value": 0 }, "next": "baseline-price" },
        "baseline-price": { "action": "eval_async", "description": "Baseline — confirm markets and price data loaded", "next": "short-background" },
        "short-background": { "action": "app_background", "when": "test_short_background", "duration_ms": "{{short_background_ms}}", "next": "short-foreground" },
        "short-foreground": { "action": "app_foreground", "next": "wait-post-short" },
        "wait-post-short": { "action": "wait_for", "next": "verify-post-short" },
        "verify-post-short": { "action": "eval_async", "description": "Confirm markets + price survive short background", "next": "long-background" },
        "long-background": { "action": "app_background", "description": "Exceeds WS grace period", "duration_ms": 30000, "next": "long-foreground" },
        "long-foreground": { "action": "app_foreground", "next": "wait-post-long" },
        "wait-post-long": { "action": "wait_for", "next": "verify-post-long" },
        "verify-post-long": { "action": "eval_async", "description": "Confirm markets + DEXs recover after WS reconnection", "next": "restart-app" },
        "restart-app": { "action": "app_restart", "when": "test_restart", "next": "detect-post-restart" },
        "...": "remaining restart/unlock/verify nodes",
        "done": { "action": "end", "status": "pass" }
      }
    }
  }
}
```

</details>

## **Validation Logs**

Command:
```bash
node scripts/perps/agentic/validate-recipe.js \
  scripts/perps/agentic/teams/perps/recipes/app-lifecycle.json
```

<details><summary>Full output (11/17 passed, 6 skipped — iOS)</summary>

```
Running recipe: App Lifecycle — validate data survives background, long background, and restart
Team: perps
Pre-conditions: wallet.unlocked, perps.feature_enabled
Workflow nodes: 20

Pre-conditions: PASS

[nav-market-list] navigate to PerpsTrendingView
  result: {"navigated":"PerpsTrendingView",...}
  PASS

[wait-markets] wait for condition
  result: {"count":291}
  PASS

[baseline-price] Baseline — confirm markets and price data loaded
  result: {"found":true,"price":"$71,046"}
  PASS

[short-background] Short background — within WS grace period, cache should be preserved
  backgrounded for 5000ms
  PASS

[short-foreground] foreground app
  foregrounded (io.metamask.MetaMask)
  PASS

[wait-post-short] wait for condition
  result: {"count":291}
  PASS

[verify-post-short] Confirm markets + price survive short background
  result: {"found":true,"price":"$71,058"}
  PASS

[long-background] Long background — exceeds WS grace period, forces full reconnection
  backgrounded for 30000ms
  PASS

[long-foreground] foreground app
  foregrounded (io.metamask.MetaMask)
  PASS

[wait-post-long] wait for condition
  result: {"count":291}
  PASS

[verify-post-long] Confirm markets + DEXs recover after full WS reconnection
  result: {"markets":291,"dexs":9,"price":"$71,039"}
  PASS

[restart-app] restart app
  [SKIPPED - when condition did not match]

[detect-post-restart] Detect login vs wallet after restart
  [SKIPPED - when condition did not match]

[check-needs-unlock] evaluate branch
  [SKIPPED - when condition did not match]

[nav-after-restart] navigate to PerpsTrendingView
  [SKIPPED - when condition did not match]

[wait-post-restart] wait for condition
  [SKIPPED - when condition did not match]

[verify-post-restart] Confirm markets reload cleanly after full restart
  [SKIPPED - when condition did not match]

----------------------------------------
Results: 11/17 passed, 6 skipped
Recipe: PASS
```

</details>

## **Pre-merge author checklist**

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

## **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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Adds new workflow actions that spawn `xcrun`/`adb` processes and
changes CDP target selection/reporting, which can affect automation
reliability across devices. Also introduces automatic log
capture/redaction and new CLI flags that alter runner behavior.
> 
> **Overview**
> **Agentic workflows can now exercise app lifecycle events.** The
recipe runner adds new actions (`app_background`, `app_foreground`,
`app_restart`) implemented via a new `lib/app-lifecycle.js` that uses
`simctl`/AppleScript on iOS and `adb` on Android, and documents these
actions plus a new `teams/perps/recipes/app-lifecycle.json` reference
recipe.
> 
> **CDP and preflight scripts now better support multi-device setups.**
`cdp-bridge.js status` probes *all* discovered Hermes targets (via new
`discoverAllTargets`) and returns either a single object or an array;
`preflight.sh` reuses an already-healthy Metro instance by probing
`/status` and loosens the platform check to a warning when the expected
platform target isn’t found.
> 
> **Recipe execution UX improved.** `validate-recipe.js` adds `--input
key=value` for overriding recipe inputs, `--no-log` to disable logging,
captures console output to `run.log` with basic redaction, and fixes
`when` guards to apply to `switch`/`end` nodes (skipping them safely
instead of executing).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
b3948ed. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## **Description**

Removed the scheduled cron trigger from
`.github/workflows/run-e2e-regression-tests-android.yml` so this
workflow no longer runs every 3 hours.

The workflow can still be run manually via `workflow_dispatch`.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: N/A

## **Manual testing steps**

```gherkin
Feature: Android regression workflow trigger behavior

  Scenario: workflow can be manually triggered only
    Given the GitHub Actions workflow file `run-e2e-regression-tests-android.yml`
    When I inspect the `on` section
    Then it contains `workflow_dispatch` inputs
    And it does not contain a `schedule` cron trigger
```

## **Screenshots/Recordings**

Not applicable (CI workflow configuration change only).

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

## **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.

<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-6074cff0-b322-43a4-898b-b8b12af5bb28"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-6074cff0-b322-43a4-898b-b8b12af5bb28"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: cmd-ob <cmd-ob@users.noreply.github.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Fix design of mush deposit page.

## **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:

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/CONF-1173

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**
<img width="395" height="853" alt="Screenshot 2026-04-10 at 4 22 11 PM"
src="https://github.com/user-attachments/assets/584fab12-a80f-4092-a57e-6ec0e662dabd"
/>

## **Pre-merge author checklist**

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

## **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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UI/prop change limited to the confirmations custom amount
view and mUSD conversion flow; main risk is unintended layout/row
visibility regressions when `hidePayTokenAmount` is enabled.
> 
> **Overview**
> Updates `CustomAmountInfo` to **remove `overrideContent`** and
introduce `hidePayTokenAmount`, which hides the default `PayTokenAmount`
(and the associated extra content block) while keeping `PayWithRow`
rendering logic consistent.
> 
> Simplifies `MusdConversionInfo` by deleting the bespoke override UI
(output tag + embedded `PayWithRow`) and instead passing
`hidePayTokenAmount` to `CustomAmountInfo`; tests are updated
accordingly.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
3c829f9. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Speed up and cancel failures no longer open a blocking **Retry** modal.
Users see a **toast** with a clear title and, when available, a short
error description—including a friendlier message when the failure is due
to **“nonce too low”** (already confirmed).

**Changes**  
- Removed `RetryModal` and related state (`retryIsOpen`, `errorMsg`,
`toggleRetry`, `retry`) from the legacy **Transactions** screen and
**UnifiedTransactionsView**.
- On failure, **legacy** `Transactions` uses `ToastService.showToast`
with shared options from `getTransactionUpdateErrorToastOptions`.
- **Unified** flow uses `ToastContext` in `useUnifiedTxActions` to show
the same toast shape.
- Centralized toast config in `app/util/confirmation/transactions.ts`
(variant, icon, colors, transparent background, copy) so both entry
points stay in sync.
- Added `resolveTransactionUpdateErrorMessage` to map raw errors to
user-facing strings where we special-case known cases.


<!--
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?
-->

## **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: Redesigned speed-up/cancel retry modal with error
toasts

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/CONF-1076

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

[toast
failed.webm](https://github.com/user-attachments/assets/3baec8fe-8513-4e99-ad14-f36c16a72043)


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

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

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

## **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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UX refactor that changes how speed-up/cancel failures are
surfaced (toast instead of a blocking modal) without altering
transaction update logic; main risk is missing toast context/service
wiring in some views.
> 
> **Overview**
> Speed-up/cancel failures no longer open a blocking **Retry** modal;
they now show an **error toast** in both the legacy `Transactions` list
(via `ToastService`) and the unified flow (via `ToastContext`).
> 
> Adds shared helpers `resolveTransactionUpdateErrorMessage` and
`getTransactionUpdateErrorToastOptions` in
`util/confirmation/transactions.ts`, including a friendlier message for
*“nonce too low”* (already confirmed), and updates tests/mocks
accordingly. Locale strings are migrated from
`transaction_update_retry_modal` to `transaction_update_toast` across
supported languages.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
d49b050. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **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?
-->

This updates the A/B testing documentation to make the implementation
path much easier for a new engineer to follow.

The guide now starts with a quickstart and definition of done,
consolidates the implementation guidance into one end-to-end example,
and moves agent-specific workflow details to an appendix so they do not
interrupt the main onboarding flow.

## **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: null

## **Related issues**

Fixes:

## **Manual testing steps**

N/A

## **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**

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

## **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.

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

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Using alert system for money account related errors.

## **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:

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/CONF-1182

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**
NA

## **Pre-merge author checklist**

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

## **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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes how `moneyAccountDeposit` “no funds” is surfaced by
introducing a new blocking alert and wiring it into the shared
pending-amount alert pipeline, which can affect confirm-button
enablement and user flow. Risk is limited to confirmations/UX and is
covered by added unit tests.
> 
> **Overview**
> Moves the `moneyAccountDeposit` “no funds” state into the
confirmations *alert system* by introducing a new blocking
`AccountNoFunds` alert (with metrics mapping) and feeding it through
`usePendingAmountAlerts`.
> 
> Removes the old inline “no funds” red text from `CustomAmountInfo`,
updates tests to assert alert-driven rendering, and adds new i18n under
`alert_system.account_no_funds` while deleting the legacy
`confirm.no_funds_use_different_account` string.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
c92ce45. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This PR syncs the stable branch to main for version 7.74.0.

*Synchronization Process:*

- Fetches the latest changes from the remote repository
- Resets the branch to match the stable branch
- Attempts to merge changes from main into the branch
- Handles merge conflicts if they occur

*File Preservation:*

Preserves specific files from the stable branch:
  - CHANGELOG.md
  - bitrise.yml
  - android/app/build.gradle
  - ios/MetaMask.xcodeproj/project.pbxproj
  - package.json

  Indicates the next version candidate of main to 7.74.0
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Wires up the Social Leaderboard to live data from the Social API.
Integrate the social-controllers (SocialService + SocialController) into
the Engine, adds useTopTraders hook using useQuery from
@metamask/react-data-query to fetch leaderboard data through the Data
Services pattern.
Also adds the homepage TopTradersSection (horizontal card carousel) and
the full TopTradersView (ranked list) with skeleton loading states.

## **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: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

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

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] 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).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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.

## **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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Adds a new Social data service/controller to the Engine and wires UI
screens to fetch live leaderboard data from a new `SOCIAL_API_URL`,
which could impact app startup/state persistence and introduce new
network failure modes.
> 
> **Overview**
> Adds live Social Leaderboard integration by introducing Engine-managed
`SocialService` and `SocialController` (new messengers, init wiring,
persisted state, and data-service registration) and configuring a new
`SOCIAL_API_URL` build/env constant.
> 
> Updates the homepage `TopTradersSection` to fetch and render the top 3
traders (cards + skeleton loading, refresh via ref, hide when empty/flag
off) and upgrades `TopTradersView` to display the full ranked list with
a network filter entry point and follow toggles.
> 
> Includes new UI components (`TopTraderCard`, `TraderRow`, skeletons,
`NetworkFilterButton`), a `formatPnl` formatter, the `useTopTraders`
hook built on `@metamask/react-data-query`, plus expanded unit tests and
updated mocks/strings.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
5881e59. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**
https://consensyssoftware.atlassian.net/browse/RWDS-1163

### Leaderboard tier selector
- Replaced TabsBar with a Pressable trigger that opens a
RewardsSelectSheet bottom sheet for tier selection
- Created RewardsSelectSheet -- a generic, reusable select bottom sheet
registered as a transparentModal in MainNavigator.js at
Routes.MODAL.REWARDS_SELECT_SHEET. Accepts title, options,
selectedValue, and onSelect callback
- Default tier is the user's projected tier (from leaderboard position)
when available, otherwise the top tier (last in list)

### Stats summary
- Added CampaignStatsSummary component displaying Return, Market Value,
Rank, and Tier in a 2x2 grid with loading skeletons and error banners

### Leaderboard neighbor display (preview mode)
- When maxEntries is set and the user's tier matches the selected tier:
- If user rank is within visible range: highlights their row with
bg-background-muted
- If user rank is outside visible range: shows top 3 entries + dot
separator + neighbor entries (rank-1, user, rank+1)
- Handles edge cases: first/last in tier (1-2 neighbors), tier mismatch,
no position data

### Pending tag / Qualified tag
- Add `qualified` and `qualifiedDays` to CampaignLeaderboardEntry and
CampaignLeaderboardPositionDto
- Display `Pending` Tag if qualified: false, `Qualified` tag if true

### Activity view
- Group activity rows by date

### Prize pool
- Add prize pool progress bar according to hardcoded breakpoints given
by PRD
- Fetch total deposit volume from new endpoint
Get(':campaignId/stats/deposits')

<!--
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?
-->

## **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: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

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

### **Before**

<!-- [screenshots/recordings] -->

### **After*

### Pending
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-09 at 17 59 47"
src="https://github.com/user-attachments/assets/bfdcec83-6f2b-4c29-b416-35b1c3275be9"
/>

<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 15 15 05"
src="https://github.com/user-attachments/assets/500d7428-f0bc-40f1-ace7-c7048b38e23f"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 15 15 41"
src="https://github.com/user-attachments/assets/a0af5d73-a265-4c0b-b8c7-d9f928cc10e3"
/>

<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 15 18 33"
src="https://github.com/user-attachments/assets/c695d664-4465-4f07-9027-668ae1d2fd7d"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 15 18 40"
src="https://github.com/user-attachments/assets/a1a0da1a-31ed-4207-bf4f-379485655cb5"
/>

### Qualified
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 15 20 27"
src="https://github.com/user-attachments/assets/29b8def5-4d08-4cf0-9e2f-3272ecdf93c2"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 15 20 31"
src="https://github.com/user-attachments/assets/9e0c3c85-7a10-4f50-8418-8d40b5f29afb"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 15 23 10"
src="https://github.com/user-attachments/assets/19f2ab07-f255-4767-b90a-e07dc8265c08"
/>

### Activity view
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 15 28 48"
src="https://github.com/user-attachments/assets/e8b42158-b6ff-47e9-b44d-ab23ba87ecc1"
/>

### Prize pool
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 17 24 02"
src="https://github.com/user-attachments/assets/ac0b1219-2252-41ed-bd26-656f188076eb"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 17 29 36"
src="https://github.com/user-attachments/assets/6f47ff55-db28-4318-919d-ce50319d0010"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-04-10 at 17 29 58"
src="https://github.com/user-attachments/assets/c4d64e3a-aa0d-44bf-bd50-8f9703986acf"
/>


*

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Moderate UI/behavior changes in Rewards campaign flows plus a new data
fetch (`getOndoCampaignDeposits`) and updated leaderboard rendering,
which could affect navigation and correctness of displayed stats/tier
selection.
> 
> **Overview**
> Updates Ondo campaign rewards UI to support **tier-based
leaderboards** via a new reusable `RewardsSelectSheet` modal (registered
in `MainNavigator`) and localized tier display names.
> 
> Reworks campaign details/leaderboard presentation by replacing
`OndoLeaderboardPosition` with a new `CampaignStatsSummary`
(return/market value/rank/tier, pending/qualified tags, SWR-style
loading/error handling), adding a `OndoPrizePool` progress section
backed by a new `useGetOndoCampaignDeposits` hook, and enhancing
`OndoLeaderboard` with preview mode (`maxEntries`), current-user
highlighting, and neighbor/split-view rendering.
> 
> Refactors the portfolio activity view to be **activity-only**, grouped
by date headers, and updates activity rows to support `timeOnly`, signed
USD formatting, and external outflow address shortening; tests are
updated/added accordingly.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
ecd1e4b. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…-3331] (#28337)

## **Description**

When selecting a token in the UB2 Buy flow, a quick error ("We've
encountered an error") flashes on the amount input screen before the
correct "Powered by [provider]" text appears.

The root cause is a provider ID mismatch: the quotes API can return
provider IDs in a prefixed format (`/providers/transak`) while the
controller state stores them without the prefix (`transak`). This caused
`selectedQuote` to resolve to `null`, briefly rendering the error
banner.

The fix normalizes provider IDs on both sides of the comparison using
`normalizeProviderCode()` and switches from array destructuring to
`.find()` so all returned quotes are searched.

## **Changelog**

CHANGELOG entry: Fixed Buy amount screen sometimes showing a generic
error when quotes returned for the selected provider but provider id
strings differed in format.

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TRAM-3331
Based on draft PR #27779

## **Manual testing steps**

```gherkin
Feature: Token selection in Buy flow

  Scenario: user selects a token and navigates to amount input
    Given user is on the token selection screen in the Buy flow

    When user selects a token (e.g. ETH)
    Then the amount input screen shows "Powered by [provider]" without any error flash
```

## **Screenshots/Recordings**

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

### **Before**

<!-- [screenshots/recordings] -->
N/A. Reason: This is an extremely rare race condition. It doesn't happen
often, and after several changes on main, it's even less common.
Nevertheless, we still want to solve this logical condition via this PR.

### **After**

<!-- [screenshots/recordings] -->
N/A. Reason: This is an extremely rare race condition. It doesn't happen
often, and after several changes on main, it's even less common.
Nevertheless, we still want to solve this logical condition via this PR.


## **Pre-merge author checklist**

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

## **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.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches Buy flow quote-selection and payment-method loading state;
small logic changes but in a user-critical conversion path and could
affect when errors/continue button appear.
> 
> **Overview**
> Prevents the Buy amount input screen from briefly showing the generic
*no quotes* error by updating `BuildQuote` to **normalize provider IDs**
(handling `/providers/...` vs short codes) and to **search all returned
quotes** via `.find()` when deriving `selectedQuote`.
> 
> Tightens `useRampsPaymentMethods` loading behavior so `isLoading`
stays true while auto-selecting a payment method when the previously
selected method is no longer present, avoiding UI flashes of stale
selection. Adds targeted tests covering provider-ID matching scenarios,
empty/mismatched quote responses, continue-button disabled state, and
the stale-selection loading fallback.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
2d4d9d7. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…saction confirmation (#28040)

## Summary
- Fixes a race condition in `Toast.showToast` where rapid successive
calls (e.g., transaction approved + confirmed in the same tick on Linea)
cause the success toast to persist indefinitely
- Tracks pending `setTimeout` with a ref so only the latest `showToast`
call wins, ensuring the success toast renders with its proper
auto-dismiss animation
- Adds test coverage for the rapid successive `showToast` scenario


https://github.com/user-attachments/assets/12064e1e-3beb-4d36-82e3-3237b2045eb6

## Test plan
- [x] Toast unit tests pass (`yarn jest
app/component-library/components/Toast/Toast.test.tsx`)
- [x] Manual: trigger a Max DAI→mUSD conversion on Linea and verify the
success toast auto-dismisses after ~3s
- [x] Verify normal (non-rapid) toast transitions still work correctly

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches toast display timing/animation logic; small but could regress
toast sequencing or dismissal behavior if timer clearing interacts with
existing transitions.
> 
> **Overview**
> Fixes a race in `Toast.showToast` where back-to-back calls could leave
multiple queued `setTimeout` updates, causing the wrong toast
state/timeout behavior (e.g., a success toast persisting).
> 
> `Toast` now tracks and clears any pending `setTimeout` via a ref so
only the latest `showToast` call applies. Adds a unit test asserting
rapid successive calls leave a single pending timer and only the latest
toast renders.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
111df6d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **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?
-->
Bringing the following changes to the client:

```markdown
## [1.25.2]

### Fixed

- Relax Trongrid `internal_transactions` validation to avoid sync failures on sparse legacy payloads ([#289](MetaMask/snap-tron-wallet#289))
- Handle TRC10 token identifiers correctly in the current Trongrid account-history transaction flow, without mis-parsing endpoint-specific `asset_name` formats ([#289](MetaMask/snap-tron-wallet#289))
- Decouple assets and transactions synchronization so one failure does not prevent the other from completing ([#289](MetaMask/snap-tron-wallet#289))
```

## **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: null

## **Related issues**

n/a

## **Manual testing steps**

n/a

## **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**

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

## **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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk dependency bump confined to the Tron snap package; behavior
changes are limited to Tron sync handling and should not affect
unrelated wallet flows.
> 
> **Overview**
> Bumps `@metamask/tron-wallet-snap` from `^1.25.1` to `^1.25.2`,
updating both `package.json` and `yarn.lock` resolution/checksum.
> 
> This pulls in upstream fixes around Tron sync robustness (more
permissive Trongrid `internal_transactions` validation, correct TRC10
token identifier handling, and separating asset vs transaction sync so
one failure doesn’t block the other).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
235931c. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…nd update result properties (#28645)

## **Description**

Rename `initModularizedControllers` to `initMessengerClients`, drop
`existingControllersByName`, rename `controllerInitFunctions` to
`initFunctions`, and update return type to `messengerClientsByName`.
Update all consumers in `Engine.ts`, `utils.test.ts`, and test utility
functions.

80 files changed. **PR 3 of 4** — depends on PR 2 (#28641).
- ~~PR 1: Core type renames (`Controller` → `MessengerClient`, etc.)
(#28610)~~
- ~~PR 2: `CONTROLLER_MESSENGERS` → `MESSENGER_FACTORIES` (#28641)~~
- **PR 3 (this):** `initModularizedControllers` → `initMessengerClients`
+ utils/Engine.ts renames
- PR 4: Property renames (`controller` → `messengerClient`,
`getController` → `getMessengerClient`) in all init files + tests

Relates to
[WPC-916](https://consensyssoftware.atlassian.net/browse/WPC-916).

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/WPC-916

## **Manual testing steps**

```gherkin
Feature: Messenger client init system

  Scenario: App builds and runs normally
    Given the app is built from this branch

    When user opens the app
    Then the app behaves identically to main (no runtime behavior change)
```

## **Screenshots/Recordings**

N/A — no UI changes.

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

## **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.

[WPC-916]:
https://consensyssoftware.atlassian.net/browse/WPC-916?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Refactors the Engine’s initialization wiring for all
controller/messenger clients, so mistakes could break startup order or
dependency resolution despite being a rename-focused change.
> 
> **Overview**
> **Renames and reshapes the Engine init helper** by replacing
`initModularizedControllers` with `initMessengerClients`, renaming
`controllerInitFunctions` to `initFunctions`, and returning
`messengerClientsByName`.
> 
> **Simplifies initialization state** by dropping support for
`existingControllersByName` and updating the dependency lookup
helper/error messaging to `getMessengerClientOrThrow`.
> 
> Updates `Engine.ts` wiring and a large set of controller init tests to
use the new request mock helper (`buildMessengerClientInitRequestMock`)
and the new result property names.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
80bf6e1. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

This PR polishes the Money feature so the patterns for Headers, List,
Sections, Filtering and Spacing are visually cohesive.

## **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: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: Money account activity and hub layout polish

  Scenario: User opens Money activity from the Money hub
    Given the user is logged in with a Money account that can show activity
    And the user is on the Money hub (home) screen

    When the user navigates to Money activity (Activity)
    Then the activity screen loads with the expected header and back affordance
    And activity is grouped and readable (date sections and list items render without layout overlap)

  Scenario: User filters Money activity by type
    Given the user is on the Money activity screen
    And there is activity data available for more than one filter category

    When the user changes the activity filter (e.g. All / Deposits / Transfers as applicable)
    Then the list updates to match the selected filter
    And section headers and row content remain correctly aligned and legible

  Scenario: User reviews Money hub summary and quick actions after layout updates
    Given the user is on the Money hub (home) screen

    When the user views the balance summary and the primary action buttons row
    Then balances and labels use the updated typography and spacing (no clipped text or misaligned controls)
    And primary actions remain tappable with expected labels and icons
```

## **Screenshots/Recordings**

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

### **Before**

<img width="1462" height="680" alt="Screenshot 2026-04-13 at 4 30 22 PM"
src="https://github.com/user-attachments/assets/38255e3a-a6c7-4ada-9a5b-7a0b5406eba0"
/>



### **After**

<img width="1442" height="643" alt="Screenshot 2026-04-13 at 4 30 37 PM"
src="https://github.com/user-attachments/assets/5bf37578-baf5-4b7f-8391-2a9611bb11c1"
/>




## **Pre-merge author checklist**

- [ ] 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).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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.

## **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.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk visual-only tweaks to layout, spacing, and typography within
Money screens; main risk is minor UI regressions like
truncation/clipping on edge device sizes.
> 
> **Overview**
> Improves visual cohesion across Money hub and activity screens by
adjusting padding/spacing, alignment, and typography in headers, section
headers, lists, and filter buttons.
> 
> Updates action buttons and activity rows to better handle sizing and
truncation (larger icons/avatars, centered/stretch layouts,
`min-w-0`/`shrink` Tailwind classes), and lightly refines secondary text
weights and button container padding for consistency.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
5ae2126. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Feature Flag Registry Drift Report

Feature flag drift was detected between E2E tests and production.

Download the [`drift-report`
artifact](https://github.com/MetaMask/metamask-mobile/actions/runs/24060043070)
for the full report.

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Priya <priya.narayanaswamy@consensys.net>
## **Description**

New: Campaign Stats Screen

A dedicated screen showing the user's personal performance in the
campaign — their current return (positive in green, negative in red),
total portfolio value, rank, tier (Bronze, Silver, Platinum), net
deposit amount, days held, and whether they're Qualified or Pending.

New: Tier-based Leaderboard

The leaderboard now lets users filter by tier (Bronze, Silver,
Platinum). Each entry shows rank, referral code, and return percentage.
Users see their own position highlighted, plus a count of total
participants in that tier.

New: "Qualify for this rank" & "You're qualified" cards

- If a user is pending, they see a card telling them exactly how much
more they need to deposit and how many more days to hold to qualify.
- Once they meet the requirements, the card flips to "You're qualified."

New: After-Hours Trading popup

When a user tries to swap an asset outside market hours, a popup appears
explaining that trading is closed, shows a countdown to when markets
reopen, and warns about wider price spreads.

New: Eligibility warning popup

If there aren't enough days left in the campaign to meet the holding
requirement, a warning popup tells the user their new position won't
count toward the campaign, with options to cancel or proceed anyway.

New: "Entries closed" state

If the campaign has ended and the user never opted in, the join button
is locked and shows "Entries closed." Tapping it shows a message
explaining they missed the opt-in window.

Updated: Portfolio section

Now shows each deposited asset with its current value, shares owned, and
profit/loss percentage. Users can tap a position to swap it for a
different asset, or tap a link to view their full activity history.

Updated: Prize pool display

Shows the current prize pool size and how much additional volume is
needed to unlock the next reward tier.

## **Changelog**


CHANGELOG entry: ondo campaign rewards - stats page

## **Screenshots/Recordings**

- Active Campaign

- Opted in

Negative return but qualified

<img width="952" height="1763" alt="negative-qualified"
src="https://github.com/user-attachments/assets/0e27784a-f5ce-4033-b338-e2916a259427"
/>

<img width="952" height="1763" alt="negative-qualified-2"
src="https://github.com/user-attachments/assets/d07d0535-b2a1-4603-b4b4-4be694dc33c7"
/>

Positive return but pending

<img width="1025" height="1799" alt="positive-pending-1"
src="https://github.com/user-attachments/assets/b4e231a0-a0af-45db-90a8-572551c8322d"
/>

<img width="1025" height="1799"
alt="positive-pendin-2-leaderboard-bottom-20"
src="https://github.com/user-attachments/assets/14e37219-9605-466b-b788-507527fce233"
/>

Leaderboard top 5 (in others its 18th position)

<img width="943" height="539" alt="leaderboard-top-5"
src="https://github.com/user-attachments/assets/55c98e89-0c94-494d-882b-b02516ef6731"
/>

Prize pool variants

<img width="962" height="324" alt="prize-pool-fully-reached"
src="https://github.com/user-attachments/assets/c154f79a-723b-4fa8-ba9b-5885b3fd541b"
/>

<img width="962" height="324" alt="prize-pool-unlock"
src="https://github.com/user-attachments/assets/da6f91f0-d12c-4654-a87d-680412769d4d"
/>

Leaderboard page (positive return pending)

<img width="1025" height="1799" alt="positive-pending"
src="https://github.com/user-attachments/assets/636d6806-c6ee-4635-bd07-6e2761919db0"
/>

Stats page positive but pending

<img width="952" height="1763" alt="positive-pending"
src="https://github.com/user-attachments/assets/6d5c8d1f-e519-47b6-9b43-e26a4df7c8dc"
/>

Stats page positive & qualified 

<img width="951" height="1830" alt="positive-qualified-complete"
src="https://github.com/user-attachments/assets/570f8f11-1d4e-415f-ab48-a0e70a747b47"
/>

Stats page but negative return and cashed out

<img width="952" height="1763" alt="negative-qualified-cashed-out"
src="https://github.com/user-attachments/assets/9298e079-30ff-4625-8ac1-eec3890df4fb"
/>

Open position or swap position but outside of market hours

<img width="957" height="845" alt="open-position-market-hours"
src="https://github.com/user-attachments/assets/52accff5-3d36-4e0b-af50-a2062fb58b78"
/>

Open position but can't qualify for tier treshold  anymore

<img width="1156" height="701" alt="not eligible"
src="https://github.com/user-attachments/assets/b67d484a-0977-4d63-bec5-f4f414273ca4"
/>

- Not Opted in

<img width="916" height="1813" alt="Screenshot from 2026-04-13 15-32-09"
src="https://github.com/user-attachments/assets/afc04260-729d-4867-bdd8-7caad4db9527"
/>

<img width="916" height="1813" alt="Screenshot from 2026-04-13 15-32-12"
src="https://github.com/user-attachments/assets/12cb1a91-c999-4f38-b535-e8aa8a6b6c4a"
/>




<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Adds new rewards navigation routes, screens, and bottom sheets with
updated Ondo campaign eligibility/pending logic and new `minDeposit`
data plumbing; mistakes could impact campaign UX and leaderboard/stats
rendering but do not touch security-critical flows.
> 
> **Overview**
> Introduces a dedicated **Ondo campaign Stats** screen
(`RewardsOndoCampaignStats`) and wires it into the rewards navigator,
including navigation from the campaign details stats header.
> 
> Adds new bottom sheets for **Pending** (`RewardsOndoPendingSheet`),
**After-hours trading** (`OndoAfterHoursSheet`), and **Not eligible**
(`OndoNotEligibleSheet`), and updates campaign details/portfolio/CTA
flows to gate swaps/position actions when the user can no longer meet
the `ONDO_GM_REQUIRED_QUALIFIED_DAYS` requirement.
> 
> Extends Ondo leaderboard tier data with `minDeposit` and updates
`OndoLeaderboard`/`CampaignStatsSummary` to show qualify messaging, open
the pending sheet from pending tags/cards, unify stats error handling,
and tweak prize pool/max-tier copy and various UI text/icon styles
(including ET→EST strings).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
a7be45e. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: sophieqgu <sophieqgu@gmail.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

This branch finishes the Card Home migration to `CardController` and
fixes the behavior regressions introduced while moving card auth,
cardholder state, wallet data, and spending-limit flows away from the
old SDK/React Query orchestration.

The motivation for the change was to make `CardController` the source of
truth for Card state, instead of splitting responsibility across the
Redux `card` slice, SDK helpers, and deleted React Query hooks like
`useLoadCardData` / `useGetCardExternalWalletDetails`.

Key changes in this branch:

- **Card authentication and session state now come from
`CardController`**
  - `CardAuthentication` uses `useCardAuth`.
- UI now reads controller-backed selectors such as
`selectIsCardAuthenticated`, `selectIsCardholder`,
`selectCardholderAccounts`, and `selectCardUserLocation`.
- Logout and session validation are handled through
`Engine.context.CardController`.
  - Legacy auth verification helpers and side-effect flows were removed.

- **Card Home was migrated to controller-backed data and split into
smaller hooks/components**
- `CardHome.tsx` was refactored heavily into focused components and
hooks like `useCardHomeActions`, `useCardHomeAnalytics`, and
`useCardProvisioning`.
- Snapshot-based tests touched by this work were removed in favor of
explicit assertions.

- **Push provisioning was aligned with the new controller/provider
architecture**
  - Provisioning eligibility was moved into the provider layer.
- The old Galileo-specific adapter path was removed in favor of the
controller adapter.
- US-only provisioning restrictions and provider-specific feature-flag
behavior were preserved.

- **Unauthenticated cardholder UX was added**
- Cardholders who are not authenticated now see teaser actions on Card
Home instead of a blocking login-required warning.
  - Teaser actions route to Card authentication.
- Card authentication now shows an informational auth prompt banner for
those entry points.
- Terms and Conditions / Contact support remain visible in that state
while Logout stays hidden.

- **Spending Limit / delegation flows broken by the migration were
restored**
- Card Home now passes the full spending-limit payload again
(`priorityToken`, `allTokens`, `delegationSettings`,
`externalWalletDetailsData`) instead of only `{ flow }`.
  - `CardHomeData` now carries `delegationSettings`.
- Supported tokens are enriched with `delegationContract`, which fixes
the `"Missing token configuration"` delegation failure.
- Spending Limit can pre-select the priority asset again and the token
picker no longer stalls on an infinite spinner.
- After successful delegation, `useSpendingLimit` now calls
`CardController.fetchCardHomeData()` so the updated
wallet/priority-token state appears automatically without requiring a
manual refresh.

- **Additional follow-up fixes and test coverage**
- Added/updated controller, provider, Card Home, Spending Limit,
provisioning, authentication, and utility tests.
- Replaced touched card snapshot tests with explicit assertions where
applicable.

## **Changelog**

CHANGELOG entry: Fixed MetaMask Card authentication, unauthenticated
cardholder actions, and spending limit/delegation refresh flows after
the CardController migration.

## **Related issues**

Fixes:

<!-- Add issue links if applicable -->

## **Manual testing steps**

```gherkin
Feature: Card controller migration and follow-up flow fixes

  Background:
    Given I have a build from this branch
    And I have access to a MetaMask Card test account

  Scenario: Card authentication uses controller-backed session state
    Given I am logged out of Card
    When I open Card and log in with a valid account
    Then Card Home should load successfully
    And authentication state should be preserved by CardController

    When I log out from Card
    Then CardController should clear the card session
    And I should return to the logged-out Card state

  Scenario: Unauthenticated cardholder sees teaser actions and auth prompt
    Given I am a cardholder but I am not currently authenticated
    When I open Card Home
    Then I should see teaser actions for card management
    And I should see Terms and Conditions and Contact support
    And I should not see Logout

    When I tap Manage limit
    Then the Card authentication screen should open
    And I should see the informational auth prompt banner

  Scenario: Spending Limit opens with delegation-ready token data
    Given I am authenticated on Card Home
    And I have supported card assets available
    When I tap Manage limit
    Then the Spending Limit screen should open
    And the priority asset should be pre-selected

    When I open the Token selector
    Then the asset list should load without an infinite spinner

  Scenario: Delegation refreshes Card Home automatically
    Given I am authenticated on Card Home
    And I open Spending Limit for a token that is not yet enabled
    When I complete delegation successfully
    Then I should return to Card Home
    And the token list and current priority token should refresh automatically
    And I should not need to pull to refresh manually

  Scenario: Push provisioning still respects provider/controller rules
    Given I am authenticated on Card Home with a supported eligible card
    When I review add-to-wallet availability
    Then provisioning eligibility should reflect the provider response
    And provider-specific feature flags should still be respected
```

## **Screenshots/Recordings**

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

## **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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Large refactor of `CardHome` data-flow and interaction handlers to
rely on `CardController`/new hooks, plus navigation/auth gating changes;
regressions are possible in card setup, spending-limit, and sensitive
actions (PIN/details/freeze). Mostly UI-layer changes but they touch
session/logout behavior and several user flows.
> 
> **Overview**
> **Card Home is migrated to controller-backed state and decomposed into
smaller units.** `CardHome` now renders from `useCardHomeData()` and
`CardController` selectors/capabilities, with UI split into components
like `CardAlertSection`, `CardActionsButtons`, `CardImageSection`,
`CardBalanceDisplay`, `ManageCardOptions`, and `CardHomeFooter`, plus
extracted hooks for actions/analytics/provisioning.
> 
> **Unauthenticated cardholder UX is changed from “blocked” to “teaser”
actions.** Manage options (view details/PIN, freeze toggle, cashback,
travel, manage card, etc.) can appear while unauthenticated but now
route to `Routes.CARD.AUTHENTICATION` with `showAuthPrompt: true`;
logout stays hidden.
> 
> **Auth + location handling is adjusted in `CardAuthentication`.** The
screen reads `showAuthPrompt` from route params to show a new info
banner (`CardMessageBoxType.AuthPrompt`), and location selection is now
local state (`selectedLocation`) used during login rather than
immediately calling `CardController.setUserLocation`.
> 
> **Behavioral/test updates.** Tests are updated to mock `useRoute`,
validate new teaser/navigation behavior, switch `CardHome` tests to
`useCardHomeData`, align freeze with separate `freeze/unfreeze`
mutations, update spending-limit copy expectations, and tighten
analytics expectations (don’t emit without a formatted balance).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
3baa77b. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **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?
-->

This change **bumps the build version once** in a dedicated job that
calls **`update-latest-build-version.yml`**, then triggers **iOS and
Android** through **`runway-ota-build-core`** in **parallel**. Both jobs
use **`skip_version_bump: true`** and **`source_branch`** set to the
**version-bump commit SHA** so both builds use the same tree. Downstream
steps (PR comment + Slack) now require **both** platform jobs to
succeed.

## **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: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MCWP-521

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

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

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] 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).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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.

## **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.
… markets (#28696)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **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?
-->

The Predict Picks section (used in game details) currently renders
`PredictPickItem` — a simple row showing "Picked [outcome] at $X" with
PnL. For sports markets with extended market types (spreads, totals,
player props), we need the richer `PredictPositionDetail` component that
already exists on the regular market details screen, which includes
icons, real-time preview values, percentage PnL, privacy mode support,
and a full-width cash-out button.

This PR conditionally renders `PredictPositionDetail` instead of
`PredictPickItem` inside `PredictPicks` when the market's league is in
the `extendedSportsMarketsLeagues` feature flag — following the same
flag pattern used by `useGameDetailsTabs`. When the flag is disabled (or
the market has no game/league), the existing `PredictPickItem` rendering
is preserved.

Also includes a minor cleanup: removes an unnecessary `useEffect` in
`useGameDetailsTabs` that was resetting `activeTab` when tabs changed.

## **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: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/PRED-803

## **Manual testing steps**

```gherkin
Feature: PredictPositionDetail in sports prediction picks

  Scenario: user views positions for an extended sports market
    Given the user has open positions on a sports market with a league in extendedSportsMarketsLeagues (e.g. NBA)

    When user navigates to the game details screen
    Then positions are displayed using the rich PredictPositionDetail component
    And each position shows an icon, title, shares info, real-time current value, and percentage PnL
    And each open position has a full-width "Cash out" button

  Scenario: user views positions for a non-extended sports market
    Given the user has open positions on a sports market whose league is NOT in extendedSportsMarketsLeagues

    When user navigates to the game details screen
    Then positions are displayed using the original PredictPickItem component
    And each position shows "Picked [outcome] at $X" format with PnL value

  Scenario: user views positions for a non-sports market
    Given the user has open positions on a non-sports prediction market (no game property)

    When user navigates to the market details screen
    Then positions are displayed using the original PredictPickItem component
```

## **Screenshots/Recordings**

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

### **Before**


https://github.com/user-attachments/assets/6f09c287-4371-4f4f-859c-7dbb69a673d8

### **After**


https://github.com/user-attachments/assets/a5790c3f-f276-4428-b604-a8aaed2a1ddd

## **Pre-merge author checklist**

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

## **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.

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes conditional rendering for the Picks list and adjusts tab state
behavior; also removes polling on active positions, which could affect
UI freshness and user interaction flows in game details.
> 
> **Overview**
> **Game details picks rendering is upgraded for extended sports
markets.** `PredictPicks` now checks
`selectExtendedSportsMarketsLeagues` and, when the market’s
`game.league` is enabled, renders `PredictPositionDetail` (including
forcing `CLOSED` status for claimable positions) instead of
`PredictPickItem`.
> 
> **Behavioral tweaks and coverage.** `useGameDetailsTabs` no longer
resets `activeTab` when the tab set changes, tests were updated/added
for the new picks rendering and tab behavior, and
`PredictGameDetailsContent` stops polling active positions by removing
the `refetchInterval` option.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f8c9faa. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@runway-github runway-github Bot temporarily deployed to build-production April 24, 2026 18:26 Inactive
chloeYue and others added 2 commits April 27, 2026 17:21
## Summary
Merges `stable` into the `release/7.74.00` line after
[#29233](#29233) landed
**7.73.2** on `stable`, so
[#28948](#28948)
(`release/7.74.00` → `stable`) can merge without mass conflicts.

CHANGELOG entry: null



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because it updates release CI gating and modifies Predict
trading feature-flag resolution/analytics plus onboarding
auth/marketing-consent flows, which can impact build automation and
user-facing trading/login behavior.
> 
> **Overview**
> Merges `stable` changes into the `release/7.74.0` line, including
updates to the auto RC build workflow to gate version bumps/build
triggers/commenting on a label check and to simplify the RC comment step
(shallower checkout and removal of test plan JSON upload/AI key envs).
> 
> Predict trading changes include new CLOB v2/legacy-host flag plumbing
(controller + selectors), refactoring order analytics emission to build
regular vs sensitive properties, and several buy-with-any-token UX/flow
tweaks (pay-with row visibility, suppressing pay-token alerts while
editing, init/cleanup behavior).
> 
> Also updates onboarding/auth flows (wallet deletion resets newer
onboarding state fields, OAuth rehydration now awaits marketing opt-in
sync, removes legacy iOS Google warning saga/state/selectors), adjusts
Token Details analytics to include A/B test attribution and ensures
swaps navigation resets scroll, and includes assorted test/snapshot
updates, ramps selector coverage for non-EVM addresses, and
localization/changelog/version metadata updates.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
b11b7c9. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
Co-authored-by: runway-github[bot] <73448015+runway-github[bot]@users.noreply.github.com>
Co-authored-by: Caainã Jeronimo <caainaje@gmail.com>
Co-authored-by: infiniteflower <139582705+infiniteflower@users.noreply.github.com>
Co-authored-by: sahar-fehri <sahar.fehri@consensys.net>
Co-authored-by: Prithpal Sooriya <prithpal.sooriya@users.noreply.github.com>
Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
Co-authored-by: António Regadas <antonio.regadas@consensys.net>
Co-authored-by: George Marshall <george.marshall@consensys.net>
Co-authored-by: tommasini <tommasini15@gmail.com>
Co-authored-by: TylerC <tyler.chong@consensys.net>
Co-authored-by: ieow <4881057+ieow@users.noreply.github.com>
Co-authored-by: tommasini <46944231+tommasini@users.noreply.github.com>
Co-authored-by: Wei Sun <wei.sun@consensys.net>
Co-authored-by: Cal-L <cal.leung@consensys.net>
Co-authored-by: Michal Szorad <michal.szorad@consensys.net>
Co-authored-by: Bryan Fullam <bryan.fullam@consensys.net>
Co-authored-by: João Loureiro <175489935+joaoloureirop@users.noreply.github.com>
Co-authored-by: Vince Howard <vincenguyenhoward@gmail.com>
Co-authored-by: abretonc7s <107169956+abretonc7s@users.noreply.github.com>
Co-authored-by: Matthew Grainger <46547583+Matt561@users.noreply.github.com>
Co-authored-by: Matthew Grainger <matthew.grainger@consensys.net>
Co-authored-by: Xiaoming Wang <7315988+dawnseeker8@users.noreply.github.com>
Co-authored-by: Arafet (CN - Hong Kong) <52028926+arafetbenmakhlouf@users.noreply.github.com>
Co-authored-by: Nico MASSART <NicolasMassart@users.noreply.github.com>
Co-authored-by: Gaurav Goel <grvgoel19@gmail.com>
Co-authored-by: MetaMask Bot <37885440+metamaskbot@users.noreply.github.com>
Co-authored-by: geositta <matthew.denton@consensys.net>
Co-authored-by: Javier Garcia Vera <javier.vera@consensys.net>
Co-authored-by: Luis Taniça <matallui@gmail.com>
@github-actions

This comment has been minimized.

runway-github Bot and others added 3 commits April 27, 2026 18:15
… CardController (#29376)

- fix(card): update feature flag listener on CardController (#29350)

<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**

This branch refreshes **card home data and Baanx configuration** when
**remote card feature flags** change, and fixes a **race** where a slow
**unauthenticated** `fetchCardHomeData` could overwrite state **after**
successful **submitCredentials**.

**Feature flags**

-

[`app/selectors/featureFlagController/card/index.ts`](app/selectors/featureFlagController/card/index.ts):
exports **`defaultCardFeatureFlag`** and **`resolveCardFeatureFlag`**
(empty remote payload → defaults). **`selectCardFeatureFlag`** now uses
**`resolveCardFeatureFlag`** so the same resolution rules apply in Redux
selectors and Engine.

**BaanxProvider / init**

-

[`BaanxProvider.ts`](app/core/Engine/controllers/card-controller/providers/BaanxProvider.ts):
accepts optional **`getCardFeatureFlag`** (lazy) in addition to legacy
**`cardFeatureFlag`**. A private getter resolves **`cardFeatureFlag`**
on each read so URLs/constants track the latest remote flags without
recreating the provider.
-

[`card-controller/index.ts`](app/core/Engine/controllers/card-controller/index.ts):
passes **`getCardFeatureFlag`** from
**`RemoteFeatureFlagController:getState`** +
**`resolveCardFeatureFlag`** into **`BaanxProvider`**.

**CardController**

- Subscribes to **`RemoteFeatureFlagController:stateChange`** with a
**selector** that serializes **`remoteFeatureFlags.cardFeature`** so
only meaningful card-flag updates run the handler.
- **`#handleCardFeatureFlagChange`**: if an EVM address is selected,
**`invalidateFetch()`**, clears **`cardHomeData`** / sets
**`cardHomeDataStatus`** to **`idle`**, then refetches card home data.
- **`#fetchCardHomeDataWithLogging`**: centralizes
**`fetchCardHomeData`** + **`Logger.error`** for account switch,
feature-flag refresh, **`submitCredentials`**, and
**`validateAndRefreshSession`**.
- **`#triggerCardholderCheck`** (accounts API URL path): uses
**`resolveCardFeatureFlag`** instead of ad-hoc casting.
- **`submitCredentials`**: sets **`cardHomeData`** to **`null`** and
status **`idle`**, calls **`invalidateFetch()`**, then fetches—so
in-flight unauthenticated responses cannot win over authenticated data.

**Messenger / types**

-

[`card-controller-messenger/index.ts`](app/core/Engine/messengers/card-controller-messenger/index.ts):
allows event **`RemoteFeatureFlagController:stateChange`**.
- [`types.ts`](app/core/Engine/controllers/card-controller/types.ts):
**`CardControllerAllowedEvents`** includes
**`RemoteFeatureFlagControllerStateChangeEvent`**.

**Tests**

-

[`CardController.test.ts`](app/core/Engine/controllers/card-controller/CardController.test.ts):
subscription to remote feature-flag state; handler clears state and
refetches; **`drops in-flight unauthenticated card home data after
successful auth`**.
-

[`BaanxProvider.test.ts`](app/core/Engine/controllers/card-controller/providers/BaanxProvider.test.ts):
**`getCardFeatureFlag`** read **lazily** during **`getOnChainAssets`**.

## **Changelog**

CHANGELOG entry: Card — **`CardController`** listens for
**`RemoteFeatureFlagController:stateChange`** and refetches card home
data when **`cardFeature`** changes; **`BaanxProvider`** resolves card
feature flags lazily; shared **`resolveCardFeatureFlag`**;
**`submitCredentials`** invalidates in-flight fetches and resets card
home state to avoid stale unauthenticated data after login.

## **Related issues**

Fixes: #29348

<!-- Add GitHub issue link when available, e.g. Fixes #12345 -->

## **Manual testing steps**

```gherkin
Feature: Card home and Baanx flags stay in sync with remote card feature flags

  Scenario: Remote card feature flag updates while card tab is open
    Given the user is on an EVM account with card session and card home loaded
    When remote `cardFeature` changes (e.g. rollout or config update)
    Then card home data is cleared to idle and refetched
    And Baanx-backed calls use the updated flag-derived config on subsequent requests

  Scenario: Login while an unauthenticated card home fetch is still in flight
    Given an unauthenticated card home fetch has not completed
    When the user completes submitCredentials successfully
    Then authenticated card home data wins and a late unauthenticated response does not overwrite it

  Scenario: Card feature flag change with no selected EVM address
    When RemoteFeatureFlagController emits a card-related change but no EVM address is selected
    Then the handler returns early without refetch errors
```

## **Screenshots/Recordings**

<!-- Optional: behavior is mostly data-layer; attach if you verify on
device after a forced remote flag change. -->

### **Before**

<!-- Card home could stay stale until manual refresh; rare stale data
after fast login during slow unauthenticated fetch. -->

### **After**

<!-- Card home refetches when `cardFeature` changes; submitCredentials
path drops stale in-flight unauthenticated results. -->

## **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 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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Updates card state refresh triggers and fetch invalidation logic
around auth and feature-flag changes; risk is moderate due to new event
subscriptions and potential for extra network calls or missed updates if
selectors are wrong.
> 
> **Overview**
> **Card home data now refreshes when remote `cardFeature` flags
change.** `CardController` subscribes to
`RemoteFeatureFlagController:stateChange`, clears `cardHomeData`/status
back to `idle`, invalidates any in-flight fetch, and refetches.
> 
> **Fixes a race where slow unauthenticated fetches could overwrite
authenticated state.** After successful `submitCredentials`, the
controller resets home data, bumps the fetch generation, and refetches
via a shared `#fetchCardHomeDataWithLogging` helper (also used by
account-switch and session refresh paths).
> 
> **Feature-flag resolution and consumption were tightened.** Adds
`resolveCardFeatureFlag` (and exports `defaultCardFeatureFlag`) to
normalize empty remote payloads to defaults; `BaanxProvider` can now
read flags lazily via a `getCardFeatureFlag` callback wired in
`cardControllerInit`, and the card-controller messenger/types allow the
new remote-flag stateChange event.
> 
> Tests add coverage for the new subscription behavior, the stale-fetch
drop after auth, and lazy flag reads in `BaanxProvider`.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
0d9863b. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[890ac4a](890ac4a)

Co-authored-by: Bruno Nascimento <brunonascimentodev@gmail.com>
@joaoloureirop joaoloureirop removed the auto-rc-builds enable automatic release candidate builds label Apr 27, 2026
@joaoloureirop joaoloureirop requested a review from a team as a code owner April 27, 2026 19:00
@joaoloureirop joaoloureirop changed the title release: 7.74.0 chore: release: 7.74.0 Apr 27, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🚀 RC Builds Ready for Testing

Platform Link Version
iOS TestFlight Go to TestFlight and download build 4696
Android Download from CI RC 7.74.00 (4696) — download APK artifact from the linked run
More Info
  • Version: 7.74.00
  • iOS Build Number: 4696
  • Android Build Number: 4696
  • Build Pipeline: View Pipeline

AI Test Plan

Risk Score High Risk Medium Risk Files Changed Teams Signed Off
85/100 16 8 2,593 21/21
Executive Summary

Release Focus: Major architectural refactor of Card, Perps, Predict, and Charts features alongside significant new Money hub components and advanced charting capabilities

Key Changes:

  • CardHome completely refactored from monolithic component into modular sub-components (CardActionsButtons, CardAlertSection, CardBalanceDisplay, CardImageSection, ManageCardOptions) with business logic extracted into useCardHomeActions and useCardHomeData hooks
  • Perps trading now integrates compliance gate checks before order placement, adds paginated transaction history with withdrawal tracking, and introduces PerpsStreamManager with persistent WebSocket connections
  • Predict feature receives major expansion including FeaturedCarousel with sport cards, PredictPreviewSheet context, crypto up/down markets, PredictAnalytics separation, and WebSocketManager for live price updates
  • Advanced charting overhauled with new LivelineChart component, OHLCV candlestick support, OHLCVBar display, layout-settle skeleton logic, and TradingView external link interception
  • Money hub gains MoneyActivityView, MoneyEarnings, MoneyConvertStablecoins, MoneyOnboardingCard, MoneyWhatYouGet, MoneyProgressBar, and MoneyMusdTokenRow components with full activity feed infrastructure

Critical Areas: Card feature - complete architectural overhaul with removed hooks (useGetPriorityCardToken, useLoadCardData, useCardProviderAuthentication) replaced by new data layer, Perps compliance gate integration - new gate() wrapper around order placement could block trades unexpectedly, Perps transaction history - pagination, deduplication, and withdrawal merging logic is new and complex, Predict controller refactor - analytics separated into PredictAnalytics class, method actions auto-generated, withTrace wrapper added, AdvancedChart WebView - major chartLogic.js rewrite (+3278 lines), layout-settle skeleton, TradingView link interception

Overall Risk: HIGH

Recommendation: No-go without targeted regression on Card home screen actions, Perps order placement with compliance gate, and Perps transaction history pagination. The Card feature removed 6+ major hooks and 2000+ lines of logic in favor of a new data layer - any regression in freeze/unfreeze, PIN view, card details, or asset selection could break core card functionality for existing cardholders. Perps compliance gate wrapping order placement is a critical path change. Recommend full manual regression on Card, Perps trading flow, and Predict buy flow before release.

Release Scenarios (24)

High Risk Scenarios (16)

1. Card - Home Screen Actions

Risk Level: HIGH

Why This Matters: CardHome.tsx was reduced from ~1500 lines to ~222 lines by extracting all business logic into useCardHomeActions (464 lines, new file) and useCardHomeData (111 lines, new file). Six major hooks were deleted entirely (useGetPriorityCardToken, useLoadCardData, useCardProviderAuthentication, useCardholderCheck, useGetCardExternalWalletDetails, useGetLatestAllowanceForPriorityToken). Any regression in the data flow from the new controller-based approach could silently break card actions.

Preconditions:

  • User has an active MetaMask Card (cardholder status)
  • User is authenticated with the card (selectIsCardAuthenticated returns true)
  • User has at least one supported funding token with balance (e.g., USDC on Ethereum)
  • Biometrics are enrolled on the device
  • App is on the Card Home screen

Test Steps:

  1. Navigate to Card tab and verify CardHome renders without crash - confirm card image, balance display, and action buttons are visible
  2. Tap 'Add Funds' button - verify AddFundsBottomSheet opens with correct token list from useCardHomeData hook
  3. Close AddFundsBottomSheet and tap 'Freeze Card' button - verify biometric prompt appears (withBiometricAuth wrapper)
  4. Authenticate with biometrics - verify card freeze succeeds and success toast appears with correct message from strings('card.card_home.manage_card_options.freeze_success')
  5. Verify frozen state is reflected in UI (card image shows frozen state, unfreeze button visible)
  6. Tap 'Unfreeze Card' - authenticate with biometrics - verify unfreeze toast appears
  7. Tap 'View PIN' - verify biometric prompt appears, authenticate, verify PIN bottom sheet opens with correct PIN
  8. Tap 'Card Details' - verify biometric prompt, authenticate, verify card details image loads and displays correctly

Expected Outcomes:

  • CardHome renders all sub-components (CardImageSection, CardBalanceDisplay, CardActionsButtons, ManageCardOptions, CardAlertSection) without errors
  • Freeze/unfreeze operations complete successfully with toast notifications
  • PIN and card details views open after biometric authentication
  • useCardHomeData hook provides correct primaryToken and balanceMap data
  • No crashes from removed hooks (useGetPriorityCardToken, useLoadCardData, useCardProviderAuthentication)

2. Card - Asset Selection Bottom Sheet

Risk Level: HIGH

Why This Matters: AssetSelectionBottomSheet.tsx was reduced from 363 lines to 63 lines. The entire data fetching approach changed from SDK calls (useCardSDK, useAssetBalances, useUpdateTokenPriority) to reading from Redux state via useCardHomeData. The new getAssetBalanceKey utility and useUpdateFundingPriority hook replace complex allowance-based logic. If the new data layer doesn't populate correctly, the asset selection sheet will show empty or incorrect token lists.

Preconditions:

  • User has an active MetaMask Card
  • User has multiple supported funding tokens across different networks (e.g., USDC on Ethereum, USDC on Polygon)
  • User is on the Card Home screen
  • useCardHomeData hook is returning valid availableTokens

Test Steps:

  1. Navigate to Card Home screen and tap 'Change Funding Token' or equivalent asset selection trigger
  2. Verify AssetSelectionBottomSheet opens and displays token list from homeAvailableTokens (not from navigation params or SDK calls)
  3. Verify token balances are displayed correctly using getAssetBalanceKey utility and balanceMap from useCardHomeData
  4. Verify excluded tokens (primary token shown elsewhere) are filtered from the list
  5. Select a different token from the list - verify useUpdateFundingPriority hook is called (not the removed useUpdateTokenPriority)
  6. Verify the selected token becomes the new primary funding token on Card Home
  7. Verify network badges display correctly for each token (EVM vs Solana chains)
  8. Close sheet and reopen - verify state persists correctly

Expected Outcomes:

  • Token list populates from Redux state via useCardHomeData, not from SDK direct calls
  • Token selection updates funding priority via useUpdateFundingPriority hook
  • Balance display is accurate using getAssetBalanceKey utility
  • No errors from removed useUpdateTokenPriority, useGetCardExternalWalletDetails, or useAssetBalances hooks

3. Card - Push Provisioning (Apple Wallet)

Risk Level: HIGH

Why This Matters: GalileoCardAdapter.ts (118 lines) was completely deleted and replaced with ControllerCardAdapter.ts (99 lines). The pushProvisioning/adapters/card/index.ts now exports ControllerCardAdapter instead of GalileoCardAdapter. AppleWalletAdapter.ts (187 lines) was added as a new wallet adapter. This is a complete replacement of the provisioning infrastructure.

Preconditions:

  • iOS device with Apple Wallet configured
  • User has an active MetaMask Card
  • User is on Card Home screen
  • AppleWalletAdapter is the new adapter (GalileoCardAdapter was removed)

Test Steps:

  1. Navigate to Card Home screen and locate 'Add to Apple Wallet' button
  2. Tap 'Add to Apple Wallet' - verify usePushProvisioning hook initiates correctly with new ControllerCardAdapter
  3. Verify provisioning flow starts without errors (GalileoCardAdapter was replaced by ControllerCardAdapter)
  4. If provisioning requires card data, verify ControllerCardAdapter fetches data from Engine controller (not Galileo SDK)
  5. Complete or cancel the Apple Wallet provisioning flow
  6. Verify success/error states are handled correctly
  7. Verify AddToWalletButton renders and responds to tap correctly
  8. On Android, verify Google Wallet provisioning path is not broken by the adapter changes

Expected Outcomes:

  • Apple Wallet provisioning initiates successfully with new ControllerCardAdapter
  • No crashes from removed GalileoCardAdapter
  • Provisioning providers.ts correctly routes to new adapter
  • AddToWalletButton displays correct state (available/unavailable)

4. Perps - Order Placement with Compliance Gate

Risk Level: HIGH

Why This Matters: PerpsMarketDetailsView.tsx now wraps the entire handleTradePress callback in gate() from useComplianceGate hook. The compliance gate is a new async wrapper that could silently block order placement if the compliance check fails or times out. The refactor changed from a direct function to an arrow function returning gate(async () => {...}), which changes the execution context and could affect error handling.

Preconditions:

  • User has a Perps account with sufficient balance
  • User is on the Perps Market Details screen for an active market (e.g., BTC-USD)
  • User's account is eligible for trading (not geo-blocked)
  • User's wallet address is selected (selectSelectedInternalAccountAddress returns valid address)

Test Steps:

  1. Navigate to Perps Market Details screen for BTC-USD
  2. Tap 'Long' button - verify compliance gate() wrapper executes before any order logic
  3. Verify that for an eligible user, the gate passes through and order flow proceeds normally to PerpsOrderView
  4. Navigate back and tap 'Short' button - verify same gate behavior
  5. Verify that if user has a cross-margin position, the CrossMarginWarning modal still appears after gate passes
  6. Verify geo-block modal (isEligibilityModalVisible) still triggers correctly for ineligible users after gate check
  7. Complete a full order placement (Long or Short) and verify transaction submits successfully
  8. Verify analytics events (PERPS_SCREEN_VIEWED, PERPS_UI_INTERACTION) still fire correctly after gate wrapping

Expected Outcomes:

  • Compliance gate passes for eligible users without blocking order flow
  • Order placement navigates to PerpsOrderView with correct direction and asset parameters
  • Geo-block modal appears for ineligible users
  • Cross-margin warning modal appears for users with cross-margin positions
  • Analytics events fire with correct properties

5. Perps - Transaction History Pagination

Risk Level: HIGH

Why This Matters: usePerpsTransactionHistory.ts was significantly refactored (+250 lines, -128 lines). New pagination logic with fundingCursorRef, fetchGenerationRef, and PAGE_WINDOW_MS/MAX_LOOKBACK_MS constants was added. Two new deduplication functions (deduplicateById, deduplicateByTxHash) were introduced. Withdrawal transactions are now tracked separately from deposits. The startTime/endTime parameters were removed from the hook interface. Any bug in the cursor-based pagination or deduplication could result in missing or duplicate transactions.

Preconditions:

  • User has an active Perps account with transaction history (deposits, withdrawals, trades)
  • User has more than one page of funding history (>30 days of activity)
  • User is on the Perps Transactions/History tab

Test Steps:

  1. Navigate to Perps Transactions view and verify initial transaction list loads correctly
  2. Verify deposits and withdrawals from wallet transactions appear in the list (walletDepositTransactions and walletWithdrawalTransactions)
  3. Scroll to bottom of transaction list - verify 'Load More' functionality triggers loadMoreFunding()
  4. Verify hasFundingMore flag correctly shows/hides load more button
  5. Verify isFetchingMoreFunding shows loading state during pagination
  6. Verify deduplicateById removes duplicate transactions from merged lists
  7. Verify deduplicateByTxHash prevents wallet transactions from appearing twice when they match REST API transactions
  8. Verify withdrawal transactions (walletWithdrawalTransactions) appear correctly alongside deposits

Expected Outcomes:

  • Transaction list loads initial page without duplicates
  • Pagination loads additional history correctly
  • Wallet deposits and withdrawals merge correctly with REST API data
  • No duplicate transactions appear in the list
  • Loading states display correctly during pagination

6. Perps - WebSocket Stream Manager

Risk Level: HIGH

Why This Matters: PerpsStreamManager.tsx was massively expanded (+189 lines, -28 lines) and PerpsConnectionManager.ts gained significant new logic (+67 lines). New mock provider was added for testing. usePerpsLiveAccount, usePerpsLiveOrders, and usePerpsLivePositions all received updates. The stream architecture is critical for real-time trading data and any regression could show stale prices or positions.

Preconditions:

  • User has a Perps account
  • Device has active internet connection
  • User navigates to Perps tab

Test Steps:

  1. Navigate to Perps tab and verify PerpsStreamManager initializes WebSocket connections
  2. Verify live account data (usePerpsLiveAccount) updates in real-time on the portfolio view
  3. Verify live positions (usePerpsLivePositions) update when position changes occur
  4. Verify live orders (usePerpsLiveOrders) reflect open order status changes
  5. Put app in background for 30 seconds, then foreground - verify streams reconnect via PerpsConnectionManager
  6. Toggle airplane mode on/off - verify PerpsConnectionManager handles reconnection
  7. Navigate away from Perps tab and back - verify PerpsAlwaysOnProvider maintains stream state
  8. Verify CandleStreamChannel still functions for market chart data

Expected Outcomes:

  • WebSocket streams establish and maintain connection
  • Live data updates reflect in UI within expected latency
  • Reconnection occurs automatically after network interruption
  • No memory leaks from stream subscriptions on navigation
  • PerpsAlwaysOnProvider correctly manages always-on stream lifecycle

7. Perps - Withdraw Flow

Risk Level: HIGH

Why This Matters: useWithdrawTokens.ts was reduced from 46 to 12 lines (major simplification). usePerpsWithdrawToastRegistrations.tsx is a new 148-line file. usePerpsWithdrawStatus.ts received updates. The withdrawal flow touches multiple refactored components and the new toast registration system.

Preconditions:

  • User has a Perps account with available balance to withdraw
  • User is on the Perps Portfolio or Withdraw screen

Test Steps:

  1. Navigate to Perps Withdraw screen and verify token list populates from useWithdrawTokens (refactored from 46 lines to 12 lines)
  2. Enter a withdrawal amount and verify useWithdrawValidation correctly validates the amount
  3. Submit withdrawal and verify usePerpsWithdrawStatus tracks the withdrawal state
  4. Verify usePerpsWithdrawToastRegistrations shows appropriate toast notifications for withdrawal status changes
  5. Verify withdrawal appears in transaction history after completion
  6. Test withdrawal with insufficient balance - verify error state from useWithdrawValidation
  7. Verify PerpsWithdrawView renders correctly with updated layout
  8. Verify withdrawal toast shows correct success/failure message

Expected Outcomes:

  • Withdrawal flow completes end-to-end without errors
  • Toast notifications appear for withdrawal status changes
  • Validation prevents invalid withdrawal amounts
  • Withdrawal appears in transaction history

8. Token Overview - Advanced Chart (Price.advanced.tsx)

Risk Level: HIGH

Why This Matters: Price.tsx was reduced from 146 lines to 59 lines and now acts as a router between PriceAdvanced and PriceLegacy. Price.advanced.tsx (437 lines) and Price.legacy.tsx (215 lines) are new files. PriceChart.tsx was significantly refactored with new chartRowWidth state, NoDataOverlay integration, and changed color logic. The chart color now uses LIGHT_MODE_SUCCESS_GREEN regardless of price direction (removed up/down color logic). Any regression here affects all token detail screens.

Preconditions:

  • tokenDetailsAdvancedCharts feature flag is DISABLED (confirmed in disabled flags list)
  • User navigates to any token detail screen (e.g., ETH, USDC)
  • App is on Ethereum mainnet or any supported network

Test Steps:

  1. Navigate to a token detail screen (e.g., tap ETH from wallet home)
  2. Verify Price component renders - since tokenDetailsAdvancedCharts is disabled, verify PriceLegacy (Price.legacy.tsx) is used as fallback
  3. Verify the legacy price chart renders correctly with line chart
  4. Verify time period selector (1H, 1D, 1W, 1M, 1Y) works correctly
  5. Tap on chart to verify crosshair/hover interaction works
  6. Verify price display updates when hovering over chart
  7. Verify PriceChart component renders with new NoDataOverlay when insufficient data points exist
  8. Verify CHART_EMPTY_DISPLAYED analytics event fires when chart has no data

Expected Outcomes:

  • Token detail screen loads without crash despite new Price.tsx architecture
  • PriceLegacy renders correctly as the active chart component
  • Time period navigation works correctly
  • NoDataOverlay appears when chart data is below CHART_DATA_THRESHOLD
  • Analytics event fires for empty chart state

9. AdvancedChart - WebView Chart Rendering

Risk Level: HIGH

Why This Matters: AdvancedChart.tsx gained 76+ lines of new logic including layoutSettling state, LAYOUT_SETTLE_FALLBACK_MS timer, TradingView link interception with InAppBrowser, and ohlcvSeriesStaleSnapshotRef. chartLogic.js/chartLogicString.ts had +3278 lines added. These are complex WebView-JavaScript bridge changes that could cause chart rendering failures, stuck skeletons, or broken external link handling.

Preconditions:

  • User is on a screen that uses AdvancedChart (Perps market details, token overview if advanced charts enabled)
  • Device has WebView support
  • Internet connection available for TradingView data

Test Steps:

  1. Navigate to Perps Market Details screen which uses AdvancedChart
  2. Verify chart renders with layout-settle skeleton (layoutSettling state) before CHART_LAYOUT_SETTLED message received
  3. Verify skeleton disappears after chart settles (within LAYOUT_SETTLE_FALLBACK_MS = 2500ms if no message received)
  4. Switch between time ranges (1H, 1D, 1W, 1M, 1Y) and verify ohlcvSeriesKey changes trigger new layout settle cycle
  5. Verify OHLCV candlestick data renders correctly in OHLCVBar component
  6. Tap on a TradingView external link within the chart - verify InAppBrowser opens (not external browser)
  7. Verify TRADINGVIEW_OPEN_DEBOUNCE_MS (800ms) prevents duplicate browser opens from redirect chains
  8. Verify chart handles WebView remount correctly when key changes (chartReadyCount resets)

Expected Outcomes:

  • Chart renders without blank flash or skeleton stuck state
  • Time range switching shows skeleton briefly then renders new data
  • TradingView links open in InAppBrowser
  • OHLCV bars display correctly with volume data
  • No duplicate browser opens from TradingView redirects

10. Predict - Buy Flow with Preview Sheet

Risk Level: HIGH

Why This Matters: PredictController.ts was reduced from 1060 to 570 lines with analytics extracted to PredictAnalytics class and method actions auto-generated in PredictController-method-action-types.ts. PredictPreviewSheetContext.tsx (254 lines) is entirely new. Routes/index.tsx changed significantly. usePredictBuyActions.ts gained 96 lines. Any regression in the controller refactor could break order placement.

Preconditions:

  • predictBottomSheet feature flag is DISABLED
  • predictWithAnyToken feature flag is DISABLED
  • User has USDC balance on a supported network
  • User is on the Predict feed screen
  • Polymarket markets are available

Test Steps:

  1. Navigate to Predict tab and verify PredictFeed loads markets correctly
  2. Tap on a market card to open PredictMarketDetails
  3. Verify PredictMarketDetailsTabBar renders with correct tabs
  4. Tap 'Yes' or 'No' outcome button - verify PredictPreviewSheetContext handles the action
  5. Verify PredictBuyWithAnyToken screen opens with correct market and outcome data
  6. Enter a bet amount using PredictKeypad - verify PredictQuickAmounts buttons work
  7. Verify PredictPayWithRow shows correct payment token
  8. Tap confirm/buy button - verify usePredictBuyActions executes order via PredictController

Expected Outcomes:

  • Market details load correctly from Polymarket provider
  • Buy flow navigates correctly through the new route structure
  • PredictPreviewSheetContext manages sheet state without errors
  • Order placement calls PredictController via new method action types
  • Success/error states display correctly

11. Predict - Polymarket WebSocket Live Updates

Risk Level: HIGH

Why This Matters: WebSocketManager.ts (285 lines) is entirely new. PolymarketProvider.ts gained 147 lines. utils.ts gained 167 lines with new parsing logic. This is a complete new real-time data infrastructure for Predict. Any bug in WebSocket message parsing or connection management could show stale or incorrect market prices.

Preconditions:

  • User is on Predict feed or market details screen
  • Device has active internet connection
  • Polymarket markets are available

Test Steps:

  1. Navigate to Predict feed and verify markets load with initial prices
  2. Verify WebSocketManager establishes connection to Polymarket WebSocket endpoint
  3. Wait 30 seconds and verify market prices update in real-time via useLiveCryptoPrices or market price subscriptions
  4. Navigate to a specific market details screen and verify live price updates continue
  5. Put app in background for 60 seconds, foreground - verify WebSocket reconnects
  6. Toggle airplane mode on/off - verify WebSocketManager handles reconnection with backoff
  7. Navigate away from Predict tab and back - verify subscriptions are properly cleaned up and re-established
  8. Verify PolymarketProvider correctly processes WebSocket messages via updated utils.ts

Expected Outcomes:

  • WebSocket connection establishes successfully
  • Market prices update in real-time
  • Reconnection occurs after network interruption
  • No memory leaks from WebSocket subscriptions
  • Price data correctly parsed from Polymarket WebSocket messages

12. Predict - Sell/Cash Out Flow

Risk Level: HIGH

Why This Matters: PredictSellPreview.tsx was significantly refactored (180 lines changed). usePredictCashOut.ts (76 lines) is a new hook. PredictAnalytics.ts (236 lines) is a new class that now handles all analytics previously inline in PredictController. The separation of analytics from controller logic could cause events to not fire if the new class isn't properly initialized.

Preconditions:

  • User has existing Predict positions (shares in a market)
  • User is on Predict positions or market details screen

Test Steps:

  1. Navigate to Predict positions and verify existing positions display correctly
  2. Tap on a position to open PredictSellPreview
  3. Verify PredictSellPreview.tsx renders correctly (180 lines of new/changed code)
  4. Verify usePredictCashOut hook provides correct cash out data
  5. Confirm sell/cash out action - verify PredictController.claimWithConfirmation or sell method is called
  6. Verify PredictBuyPreview also renders correctly for the buy confirmation step
  7. Verify analytics events fire correctly via new PredictAnalytics class
  8. Verify success/error states display correctly after sell

Expected Outcomes:

  • Sell preview shows correct position value and payout
  • Cash out completes successfully
  • Analytics events fire via PredictAnalytics (not inline in controller)
  • Position disappears from list after successful sell

13. Card - Onboarding / Sign Up Flow

Risk Level: HIGH

Why This Matters: SignUp.tsx gained 112 lines of changes. WaitlistFormModal.tsx (180 lines) is entirely new. OnboardingNavigator.tsx received updates. The card onboarding is a critical user acquisition flow and any regression would prevent new users from getting a card.

Preconditions:

  • User does NOT have an existing MetaMask Card
  • User is in a supported region
  • User has completed MetaMask wallet setup

Test Steps:

  1. Navigate to Card tab and verify CardWelcome screen renders for new users
  2. Tap 'Get Started' - verify OnboardingNavigator routes correctly
  3. Complete SignUp form - verify SignUp.tsx (112 lines changed) handles form submission correctly
  4. Enter phone number in SetPhoneNumber screen - verify validation works
  5. Complete PersonalDetails form - verify all fields validate correctly
  6. Enter PhysicalAddress - verify RegionSelectorModal opens and region selection works
  7. Complete VerifyIdentity step - verify navigation to next step
  8. Verify WaitlistFormModal (new 180-line component) renders and submits correctly if user is waitlisted

Expected Outcomes:

  • Onboarding flow completes all steps without crashes
  • Form validation works correctly on all screens
  • WaitlistFormModal handles waitlisted users correctly
  • Navigation between onboarding steps is correct
  • SignUp.tsx changes don't break form submission

14. Compliance Gate - Access Restricted Modal

Risk Level: HIGH

Why This Matters: useComplianceGate.ts (126 lines) is a new hook replacing useWalletCompliance.ts (deleted). It's now integrated into PerpsMarketDetailsView as a gate() wrapper around order placement. Even with complianceEnabled disabled, the hook is still instantiated and gate() is called on every trade button press. If the hook has initialization errors or gate() throws when compliance is disabled, it would block all Perps trading.

Preconditions:

  • complianceEnabled feature flag is DISABLED (confirmed in disabled flags list)
  • User is attempting to access Perps trading
  • useComplianceGate hook is integrated into PerpsMarketDetailsView

Test Steps:

  1. Navigate to Perps Market Details screen
  2. Tap 'Long' or 'Short' button - verify gate() executes
  3. Since complianceEnabled is disabled, verify gate() passes through without blocking (compliance check should be a no-op or pass-through when flag is off)
  4. Verify order flow proceeds normally to PerpsOrderView
  5. Verify AccessRestrictedModal does NOT appear for normal users
  6. Verify AccessRestrictedContext provides correct context values
  7. Verify useComplianceGate hook returns a gate function that doesn't block when compliance is disabled
  8. Verify no console errors or crashes from compliance hook initialization

Expected Outcomes:

  • Compliance gate is transparent (pass-through) when complianceEnabled flag is off
  • Perps trading works normally without compliance blocking
  • No AccessRestrictedModal appears unexpectedly
  • useComplianceGate hook initializes without errors

15. Navigation - Main Navigator Changes

Risk Level: HIGH

Why This Matters: MainNavigator.js gained 69 lines and MainNavigator.test.tsx (168 lines) is new. App.tsx gained 59 lines. Multiple route files were updated (Card routes/index.tsx, Predict routes/index.tsx, Money routes/index.tsx). Navigation is the backbone of the app and any regression could make features inaccessible.

Preconditions:

  • Fresh app install or existing user
  • App is launched and user is on wallet home screen

Test Steps:

  1. Launch app and verify MainNavigator renders without crash (69 lines added to MainNavigator.js)
  2. Navigate to each main tab (Wallet, Activity, Browser, Settings) and verify correct screens load
  3. Navigate to Card tab and verify Card routes render correctly (routes/index.tsx updated)
  4. Navigate to Perps section and verify Perps routes are accessible
  5. Navigate to Predict section and verify Predict routes render (routes/index.tsx changed significantly)
  6. Navigate to Money section and verify Money routes render (routes/index.tsx updated)
  7. Test deep link navigation if applicable - verify App.tsx changes (59 lines added) don't break deep links
  8. Test back navigation from nested screens to verify navigation stack is correct

Expected Outcomes:

  • All main navigation tabs work correctly
  • Card, Perps, Predict, and Money routes are accessible
  • Deep links navigate to correct screens
  • Back navigation works correctly throughout the app
  • No navigation crashes or blank screens

16. Earn - mUSD Claim Bonus

Risk Level: HIGH

Why This Matters: AssetOverviewClaimBonus.tsx gained 235 lines of new logic including cross-chain balance aggregation (mainnetMusdAsset + lineaMusdAsset), new TagBase bonus tag, lifetimeBonusClaimed display, and onRefetchReady callback. The cross-chain balance calculation is new and complex - if selectAsset selectors don't return correct data for both chains, the bonus estimate will be wrong.

Preconditions:

  • earnMusdConversionRewardsUiEnabled feature flag is DISABLED
  • User holds mUSD tokens on Ethereum mainnet or Linea
  • User is on the mUSD token detail/asset overview screen
  • User has claimable Merkl rewards

Test Steps:

  1. Navigate to mUSD token detail screen and verify AssetOverviewClaimBonus renders
  2. Verify balance calculation sums mUSD holdings across BOTH Ethereum mainnet AND Linea (new cross-chain balance logic)
  3. Verify estimated annual bonus displays correctly (balance × MUSD_CONVERSION_APY / 100)
  4. Verify lifetime bonus display shows '$0.00' before first claim, then '+$X.XX' after
  5. Tap 'Claim' button - verify useMerklBonusClaim executes claim
  6. Verify hasPendingClaim state shows loading during claim
  7. Verify success state after claim with updated lifetimeBonusClaimed value
  8. Verify onRefetchReady callback is called so parent can trigger refresh

Expected Outcomes:

  • Cross-chain mUSD balance correctly sums mainnet + Linea holdings
  • Annual bonus estimate is mathematically correct
  • Claim flow completes successfully
  • Lifetime bonus updates after successful claim
  • TagBase bonus tag renders with correct styling

Medium Risk Scenarios (8)

1. Money Hub - Activity View

Risk Level: MEDIUM

Why This Matters: MoneyHomeView.tsx gained 106 lines. Eight new Money components were added (MoneyEarnings, MoneyConvertStablecoins, MoneyOnboardingCard, MoneyProgressBar, MoneyMusdTokenRow, MoneyWhatYouGet, MoneyActivityItem, MoneyActivityList). MoneyWhyMetaMaskMoney and MoneyYourPosition were deleted. This is a significant UI restructuring of the Money hub.

Preconditions:

  • moneyHomeScreenEnabled feature flag is DISABLED
  • moneyEnableMoneyAccount feature flag is DISABLED
  • moneyActivityMockDataEnabled feature flag is DISABLED
  • User has Money account (if accessible despite flags)
  • User is on Money Home screen

Test Steps:

  1. Navigate to Money tab and verify MoneyHomeView renders with updated layout
  2. Verify MoneyBalanceSummary displays correct balance data
  3. Verify MoneyEarnings component renders earnings information
  4. Verify MoneyConvertStablecoins component renders if user has eligible stablecoins
  5. Verify MoneyOnboardingCard renders for new Money users
  6. Verify MoneyProgressBar renders with correct progress values
  7. Verify MoneyMusdTokenRow renders mUSD token information
  8. Verify MoneyActionButtonRow renders action buttons correctly

Expected Outcomes:

  • MoneyHomeView renders without crashes despite major component additions
  • All new Money components render correctly
  • Balance and earnings data display accurately
  • Navigation between Money screens works correctly

2. Snaps - Collapsible Section UI

Risk Level: MEDIUM

Why This Matters: SnapUICollapsibleSection.tsx (73 lines) and collapsible-section.ts (27 lines) are entirely new Snap UI components. SnapUIAccountSelector.tsx gained 49 lines. SnapUIFooterButton.tsx was refactored. The Snap UI renderer index.ts now exports collapsible-section. Any regression could break Snap UIs that use these components.

Preconditions:

  • User has a Snap installed that uses collapsible sections in its UI
  • User triggers a Snap UI that renders a collapsible section component

Test Steps:

  1. Trigger a Snap that renders a collapsible section (e.g., a Snap with expandable content)
  2. Verify SnapUICollapsibleSection renders with correct initial collapsed/expanded state
  3. Tap the collapsible section header - verify it expands to show content
  4. Tap again - verify it collapses correctly
  5. Verify SnapUIAccountSelector renders correctly with updated 49-line changes
  6. Verify SnapUIFooterButton renders and handles loading/disabled states correctly
  7. Verify SnapUISelector renders with correct options
  8. Verify Snap UI renderer correctly maps collapsible-section component type

Expected Outcomes:

  • Collapsible sections expand and collapse correctly
  • Snap UI renders all component types without errors
  • Account selector shows correct accounts
  • Footer buttons respond to user interaction

3. DeFi Positions List

Risk Level: MEDIUM

Why This Matters: DeFiPositionsList.tsx gained 69 lines and lost 21 lines - significant logic changes to the positions display. This affects users with DeFi positions who rely on this view for portfolio tracking.

Preconditions:

  • User has DeFi positions (e.g., Uniswap LP, Aave deposits)
  • User is on the DeFi Positions screen

Test Steps:

  1. Navigate to DeFi Positions screen and verify DeFiPositionsList renders
  2. Verify positions list displays correctly with updated component (69 lines added, 21 removed)
  3. Verify position grouping and display logic works correctly
  4. Tap on a position to expand details - verify accordion behavior
  5. Verify position values and token amounts display correctly
  6. Verify loading state renders correctly
  7. Verify empty state renders when no positions exist
  8. Scroll through a long list of positions and verify performance

Expected Outcomes:

  • DeFi positions list renders all positions correctly
  • Position details expand/collapse correctly
  • Values and amounts are accurate
  • Loading and empty states display correctly

4. Permission Approval Flow

Risk Level: MEDIUM

Why This Matters: PermissionApproval.tsx gained 9 lines of changes. This is a security-critical flow - any regression could cause incorrect permissions to be granted or denied.

Preconditions:

  • User has a dApp connected or is connecting a new dApp
  • User is prompted with a permission approval request

Test Steps:

  1. Connect a dApp to MetaMask and trigger permission approval
  2. Verify PermissionApproval.tsx renders correctly (9 lines added)
  3. Verify account selection in permission approval works correctly
  4. Verify network permission display is correct
  5. Approve permissions and verify dApp receives correct permissions
  6. Deny permissions and verify dApp receives rejection
  7. Verify MaliciousDappIndicators renders correctly for suspicious dApps
  8. Verify PermissionsSummary snapshot matches expected layout

Expected Outcomes:

  • Permission approval renders without errors
  • Account and network permissions display correctly
  • Approve/deny actions work correctly
  • Malicious dApp indicators show for flagged sites

5. Ramp - Buy/Sell Flow

Risk Level: MEDIUM

Why This Matters: Multiple Ramp view snapshots were deleted (BuildQuote, Checkout, OrderDetails, OrdersList, Quotes, SendTransaction, Settings) indicating significant test refactoring. BuildQuote.test.tsx gained 71 lines. The snapshot deletions suggest UI changes that need visual verification.

Preconditions:

  • User is in a supported region for Ramp
  • User has completed KYC if required
  • User is on the Buy/Sell screen

Test Steps:

  1. Navigate to Buy screen and verify BuildQuote renders correctly
  2. Select a cryptocurrency and fiat amount - verify quote generation
  3. Select a payment provider from Quotes screen
  4. Proceed to Checkout and verify payment flow
  5. Navigate to OrdersList and verify existing orders display correctly
  6. Tap on an order to view OrderDetails
  7. Navigate to Settings and verify Ramp settings render
  8. Verify SendTransaction screen renders for crypto-to-crypto ramp

Expected Outcomes:

  • Buy flow completes end-to-end without errors
  • Order history displays correctly
  • Order details show accurate information
  • Settings are accessible and functional

6. Account Right Button / Account Switcher

Risk Level: MEDIUM

Why This Matters: AccountRightButton/index.tsx gained 15 lines and index.test.tsx gained 63 lines. AccountRightButton.types.ts has a new type. This is a frequently used UI element that appears on the main wallet screen.

Preconditions:

  • User has multiple accounts (at least 2)
  • User is on the wallet home screen

Test Steps:

  1. Verify AccountRightButton renders in the navigation header
  2. Tap AccountRightButton - verify account switcher opens
  3. Verify the button correctly reflects current account state
  4. Switch to a different account - verify wallet home updates
  5. Verify AccountRightButton.types.ts new type is handled correctly
  6. Verify the button renders correctly for both EVM and non-EVM accounts
  7. Test with hardware wallet account - verify correct display
  8. Verify analytics events fire on account switch

Expected Outcomes:

  • Account right button renders correctly
  • Account switching works without errors
  • Correct account is displayed after switch
  • Button handles all account types correctly

7. Toast Notifications

Risk Level: MEDIUM

Why This Matters: Toast.tsx gained 9 lines and Toast.test.tsx gained 35 lines. Toast is used extensively by the new useCardHomeActions hook for freeze/unfreeze/PIN success messages. Any regression in toast rendering would affect user feedback for card operations.

Preconditions:

  • User is on any screen that triggers toast notifications
  • ToastContext is available

Test Steps:

  1. Trigger a card freeze action to show a toast notification
  2. Verify Toast.tsx renders correctly with new 9-line changes
  3. Verify toast auto-dismisses after timeout
  4. Verify toast with hasNoTimeout stays visible until dismissed
  5. Trigger multiple toasts in sequence - verify queue behavior
  6. Verify Icon variant toast renders with correct icon and color
  7. Verify toast renders correctly in both light and dark mode
  8. Verify toast accessibility (screen reader support)

Expected Outcomes:

  • Toast notifications appear and dismiss correctly
  • Icon toasts show correct icon and color
  • Timeout behavior works as expected
  • Multiple toasts queue correctly

8. Network Multi-Selector

Risk Level: MEDIUM

Why This Matters: NetworkMultiSelector.tsx lost 52 lines and gained 8 - significant simplification. NetworkMultiSelectorUtils.ts (84 lines) is a new utility file. The component was likely refactored to use the new utility functions, which could change behavior.

Preconditions:

  • User has multiple networks configured
  • User is on a screen that uses NetworkMultiSelector (e.g., token filtering)

Test Steps:

  1. Navigate to a screen with NetworkMultiSelector
  2. Verify network list renders correctly with updated component (8 lines added, 52 removed)
  3. Select multiple networks - verify selection state updates
  4. Deselect a network - verify it's removed from selection
  5. Verify NetworkMultiSelectorUtils.ts (84 lines, new file) utility functions work correctly
  6. Verify 'Select All' / 'Deselect All' functionality if present
  7. Apply network filter and verify results are filtered correctly
  8. Verify performance with many networks (10+)

Expected Outcomes:

  • Network multi-selector renders all configured networks
  • Multi-selection works correctly
  • Filter application produces correct results
  • Performance is acceptable with many networks

Teams Sign-off Status (21/21)

Signed off: Accounts Framework, Assets, Card, Confirmations, Core Extension UX, Core Platform, Design System, Earn, Engagement, Mobile Platform, Mobile UX, Money Movement, Networks, Onboarding, Perps, Predict, Rewards, Social AI, Swaps And Bridge, Transactions, Wallet Integrations

Excluded Features - Feature Flags Disabled (59)

The following features are disabled via feature flags and should NOT be tested:

  • addBitcoinAccountDummyFlag
  • aiSocialLeaderboardEnabled
  • aiSocialWhatsHappeningEnabled
  • assetsNftGridEnabled
  • bitcoinTestnetsEnabled
  • brazeBannerHome
  • brazeSegmentForwarding
  • complianceEnabled
  • configRegistryApiEnabled
  • coreMCU589AbtestHubPageDiscoveryTabs
  • earnFeatureFlagTemplate
  • earnMoneyHubEnabled
  • earnMusdConversionRewardsUiEnabled
  • earnPooledStakingServiceInterruptionBannerEnabled
  • earnStablecoinLendingServiceInterruptionBannerEnabled
  • forceRampsStagingEnvironment
  • fullPageAccountList
  • galileoAppleWalletInAppProvisioningEnabled
  • galileoGoogleWalletInAppProvisioningEnabled
  • googleLoginIosUnsupportedBlockingEnabled
  • hapticsKillSwitch
  • homeTMCU470AbtestTrendingSections
  • legacyIosGoogleConfigEnabled
  • moneyActivityMockDataEnabled
  • moneyEnableMoneyAccount
  • moneyHomeScreenEnabled
  • pepsSamplePhasedRolloutFlag
  • perpsDefaultPayTokenWhenNoBalanceEnabled
  • perpsMyxProviderEnabled
  • perpsPerpGtmOnboardingModalEnabled
  • perpsPerpTradingServiceInterruptionBannerEnabled
  • platformNewLinkHandlerSystem
  • predictBottomSheet
  • predictClobV2
  • predictClobV2UseLegacyClobHost
  • predictExtendedSportsMarkets
  • predictHotTab
  • predictMarketHighlights
  • predictTabFeaturedCarousel
  • predictUpDown
  • predictWithAnyToken
  • rewardsAnnouncementModalEnabled
  • rewardsBitcoinEnabled
  • rewardsDropsEnabled
  • rewardsEnableMusdDeposit
  • rewardsEnableMusdHolding
  • rewardsMissingEnrolledAccounts
  • rewardsReferralCodeEnabled
  • rewardsReferralEnabled
  • rewardsTronEnabled
  • solanaOnboardingModal
  • solanaTestnetsEnabled
  • tempoConfig
  • tokenDetailsAdvancedCharts
  • tokenDetailsV2ButtonLayout
  • tokenDiscoveryBrowserEnabled
  • transactionsTxHashInAnalytics
  • tronStaking
  • walletHomeOnboardingSteps

Generated by AI Test Plan Analyzer (claude-sonnet-4-6) at 2026-04-27T19:51:23.381Z

AI generated test plan (JSON): test-plan-7.74.00.json

joaoloureirop
joaoloureirop previously approved these changes Apr 28, 2026
@joaoloureirop joaoloureirop added the skip-sonar-cloud Only used for bypassing sonar cloud when failures are not relevant to the changes. label Apr 28, 2026
This PR updates the change log for 7.74.0-ota.0. (Hotfix - no test plan
generated.)

---------

Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
Co-authored-by: chloeYue <105063779+chloeYue@users.noreply.github.com>
Co-authored-by: Wei Sun <wei.sun@consensys.net>
Co-authored-by: chloeYue <chloe.gao@consensys.net>
Co-authored-by: João Loureiro <175489935+joaoloureirop@users.noreply.github.com>
@joaoloureirop joaoloureirop added the no-changelog no-changelog Indicates no external facing user changes, therefore no changelog documentation needed label Apr 28, 2026
@metamaskbotv2 metamaskbotv2 Bot added the INVALID-PR-TEMPLATE PR's body doesn't match template label Apr 28, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

⏭️ Smart E2E selection skipped - base branch is not main or a release branch (base: stable)

All E2E tests pre-selected.

View GitHub Actions results

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

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

See analysis details on SonarQube Cloud

@joaoloureirop joaoloureirop merged commit f9ccf4f into stable Apr 28, 2026
69 of 78 checks passed
@joaoloureirop joaoloureirop deleted the release/7.74.00 branch April 28, 2026 19:06
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 28, 2026
@chloeYue chloeYue restored the release/7.74.00 branch May 4, 2026 08:40
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

INVALID-PR-TEMPLATE PR's body doesn't match template no-changelog no-changelog Indicates no external facing user changes, therefore no changelog documentation needed size-XL skip-sonar-cloud Only used for bypassing sonar cloud when failures are not relevant to the changes. team-mobile-delivery

Projects

None yet

Development

Successfully merging this pull request may close these issues.