Skip to content

[pull] main from MetaMask:main#621

Merged
pull[bot] merged 104 commits into
Reality2byte:mainfrom
MetaMask:main
Mar 23, 2026
Merged

[pull] main from MetaMask:main#621
pull[bot] merged 104 commits into
Reality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Mar 23, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

metamaskbot and others added 30 commits March 12, 2026 19:39
…cking cp-7.70.0 (#27455)

- feat: MUSD-454 add quick convert event tracking (#27305)

<!--
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**
### Changes:
- Adds Segment event tracking for the mUSD Quick Convert flow
- Enriches generic `Transaction*` events for `musdConversion`
transactions
- Adds `confirmation_source` to differentiate between the "Max" convert
bottom sheet and custom amount confirmations
- Adds `is_max` which is `true` when "Max" conversion flow is used or
when custom amount is used and user clicks "Max" button in percentage
button row
  - Adds mUSD quote tracking data 

### Events
| Event | Type | Location | Description |
|---|---|---|---|
| `mUSD Quick Convert Screen Viewed` | New standalone event |
`MusdQuickConvertView` (on mount) | Fires when the quick convert token
list screen is viewed |
| `mUSD Bonus Terms of Use Pressed` | New standalone event |
`MusdQuickConvertView` (`quick_convert_home_screen`),
`EarnMusdConversionEducationView` (`conversion_education_screen`),
`useMusdConversionNavbar` (`custom_amount_navbar`), `PercentageRow`
(`percentage_row`) | Fires when user presses the bonus terms of use
link; `location` property differentiates the source |
| `mUSD Quick Convert Token Row Button Clicked` | New standalone event |
`MusdQuickConvertView` | Fires on "Max" or "Edit" button tap; includes
`button_action`, `redirects_to`, asset details |
| `confirmation_source` | New property on `Transaction*` events |
`useMusdConversionConfirmationMetrics` |
`'quick_convert_max_bottom_sheet_confirmation_screen'` or
`'custom_amount_screen'` — only attached to `musdConversion`
transactions |
| `is_max` | New property on `Transaction*` events |
`useMusdConversionConfirmationMetrics` | Derived from
`TransactionPayController.isMaxAmount` — only attached to
`musdConversion` transactions |
| Quote tracking data | New properties on `Transaction*` events |
`useMusdConversionConfirmationMetrics` | Standardized quote/pay data via
`getMusdConversionQuoteTrackingData` — only attached to `musdConversion`
transactions |

<!--
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 Segment event tracking for mUSD Quick Convert
flow and enrich generic Transaction* events for mUSD conversion
transactions

## **Related issues**

Fixes: [MUSD-454: Add segment events for Quick Convert
flow](https://consensyssoftware.atlassian.net/browse/MUSD-454)

## **Manual testing steps**

```gherkin
Feature: mUSD Quick Convert Segment event tracking

  Scenario: user views the quick convert screen
    Given user navigates to the mUSD Quick Convert screen

    When the screen mounts
    Then "mUSD Quick Convert Screen Viewed" event fires with location "quick_convert_home_screen"

  Scenario: user taps Max on a token row
    Given user is on the mUSD Quick Convert screen with convertible tokens

    When user taps "Max" on a token row
    Then "mUSD Quick Convert Token Row Button Clicked" event fires with button_action "max" and redirects_to "quick_convert_max_bottom_sheet_confirmation_screen"

  Scenario: user taps Edit on a token row
    Given user is on the mUSD Quick Convert screen with convertible tokens

    When user taps the edit icon on a token row
    Then "mUSD Quick Convert Token Row Button Clicked" event fires with button_action "custom" and redirects_to "custom_amount_screen"

  Scenario: user taps "Terms apply" link on the quick convert screen
    Given user is on a screen displaying the mUSD bonus "Terms apply" link

    When user taps "Terms apply"
    Then "mUSD Bonus Terms of Use Pressed" event fires with the location of the current screen

  Scenario: user confirms a max mUSD conversion
    Given user is on the max convert bottom sheet confirmation

    When user taps "Convert"
    Then "Transaction Approved" event includes confirmation_source "quick_convert_max_bottom_sheet_confirmation_screen", "is_max: true", and quote tracking data

  Scenario: user confirms a custom amount mUSD conversion
    Given user is on the custom amount conversion screen

    When user taps "Convert"
    Then "Transaction Approved" event includes confirmation_source "custom_amount_screen", "is_max: false"
```

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

- [ ] 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 MetaMetrics events and confirmation-metric dispatches across
mUSD conversion/confirmation screens; while behavior is mostly
observational, it touches confirmations flow and transaction status
tracking and could affect analytics payloads or introduce unintended
side effects if hooks fire unexpectedly.
> 
> **Overview**
> Adds **MetaMetrics tracking for the mUSD Quick Convert flow**,
including `MUSD_QUICK_CONVERT_SCREEN_VIEWED`,
`MUSD_QUICK_CONVERT_TOKEN_ROW_BUTTON_CLICKED` (Max/Edit), and
`MUSD_BONUS_TERMS_OF_USE_PRESSED` with location/context properties.
> 
> Introduces a shared analytics utility
(`getMusdConversionQuoteTrackingData` + `deepSnakeCaseKeys`) and
refactors `useMusdConversionStatus` to use it when emitting
`MUSD_CONVERSION_STATUS_UPDATED`, standardizing quote-derived
properties.
> 
> Enriches **confirmation metrics for `musdConversion`** by adding a new
`useMusdConversionConfirmationMetrics` hook (wired into
`MusdConversionInfoRoot`) that dispatches `confirmation_source`,
`is_max`, and select quote fields into `confirmationMetrics`. Tests are
updated/added accordingly, and `EVENT_LOCATIONS`/`MetaMetricsEvents` are
extended to support the new instrumentation.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6e2e686. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[15edc39](15edc39)

Co-authored-by: Matthew Grainger <46547583+Matt561@users.noreply.github.com>
Resolved conflicts between stable (7.69.0) and release/7.70.0:

Build/version: take release/7.70.0 versions (7.70.0, build 4020)
- android/app/build.gradle, ios project, bitrise.yml

Dependencies: take release/7.70.0 versions
- package.json, yarn.lock

Source code: take release/7.70.0 (newer features and fixes)
- Bridge, Perps, Predict, TokenList, confirmations, HyperLiquidProvider
- All locale files (de, el, es, fr, hi, id, ja, ko, pt, ru, tl, tr, vi, zh)

Merge with "Create a merge commit" — do NOT squash.

Made-with: Cursor
The provider code comes from stable (7.69.0) but the test was taken
from release/7.70.0 during conflict resolution, causing mock mismatches.
Take stable's test to match the provider.

Made-with: Cursor
The test must match release/7.70.0's provider, not stable's.
Reverting to release/7.70.0's test so merging this PR doesn't
break the release branch.

Made-with: Cursor
## **Description**

Sync stable branch into release/7.70.0 to include hotfix releases
(7.68.1, 7.68.2) that were merged to stable.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: Stable sync

  Scenario: release branch includes latest stable changes
    Given the release/7.70.0 branch exists

    When stable is synced into release/7.70.0
    Then the release branch includes all hotfix changes from stable
```

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

Made with [Cursor](https://cursor.com)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Documentation-only change updating `CHANGELOG.md`; no runtime code
paths are affected.
> 
> **Overview**
> **Updates release documentation** by adding a new `7.69.0` section to
`CHANGELOG.md` with consolidated Added/Changed/Fixed entries.
> 
> Also adds `7.68.1` and `7.68.2` sections and updates the bottom
compare links so `[Unreleased]` now compares from `v7.69.0` and includes
new version link references.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a0eca7f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ore tab icon cp-7.69.1 cp-7.70.0 (#27489)

- refactor: Reverted selected state for explore tab icon cp-7.69.1
cp-7.70.0 (#27459)

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

Updates the Explore (Trending) tab icon in the main tab bar from the
filled variant to the outline variant.

## **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: Updated Explore tab icon in the main tab bar to use the
outline style.

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/DSYS-578

## **Manual testing steps**

```gherkin
Feature: Explore tab icon in tab bar

  Scenario: Explore tab shows outline search icon
    Given the app is open and the user is on any main tab

    When the user views the tab bar
    Then the Explore (Trending) tab shows the outline search icon (not the filled variant)
    And the icon is visible and correctly aligned with other tab icons
```

## **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/e9d96e13-1420-4db6-8353-3de9fd0b06a9


<!-- [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 visual-only change that swaps the selected-state icon for the
Explore/Trending tab; no navigation, analytics, or data flows are
affected.
> 
> **Overview**
> Updates the TabBar selected-state icon mapping for the
Explore/Trending tab to use the outline `IconName.Search` instead of the
filled `IconName.SearchFilled`, reverting its “active” appearance to
match the outline style.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
829d018. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[2d1ed07](2d1ed07)

Co-authored-by: Brian August Nguyen <brianacnguyen@gmail.com>
…r with safeareaview cp-7.69.1 cp-7.70.0 (#27491)

- fix: Updated root pages scrollable behavior with safeareaview
cp-7.69.1 cp-7.70.0 (#27446)

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

Standardizes safe area and header inset behavior across the main tab
views (Wallet, Explore, Activity, Rewards).

1. **Reason for the change:** These views used `edges={{ bottom:
'additive' }}` on `SafeAreaView` and `includesTopInset` on headers,
which was inconsistent with the desired layout and could cause double
insets or incorrect safe area handling.
2. **Improvement:** Switched to `edges={{ top: 'additive' }}` on
`SafeAreaView` and removed `includesTopInset` from header components so
the top safe area is handled by the screen container and headers align
consistently.

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

## **Manual testing steps**

```gherkin
Feature: Safe area and header insets on main tabs

  Scenario: Wallet, Explore, Activity, and Rewards use consistent safe area
    Given the app is open on a device or simulator with a notch/safe area

    When the user switches to each main tab (Wallet, Explore, Activity, Rewards)
    Then the top safe area is applied by the screen (no double inset)
    And the header (title + accessories) aligns correctly below the safe area
    And the bottom of each view respects the tab bar / device safe area as before
```

## **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/0eda5978-7bd5-4428-86ea-f62637fb06ed


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

### **After**



https://github.com/user-attachments/assets/a8ff8e19-a49e-41f4-9056-7c2271da8c66


<!-- [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**
> Layout-only changes to core tab screens
(Wallet/Explore/Activity/Rewards) that can affect safe-area padding and
scroll behavior across devices, plus removal of Wallet’s bottom
fade/scroll tracking logic which could subtly change UX on the homepage.
> 
> **Overview**
> Standardizes safe-area handling across the main tab views by switching
root `SafeAreaView` usage from `edges={{ bottom: 'additive' }}` to
`edges={{ top: 'additive' }}` and removing header `includesTopInset` so
the top inset is applied consistently by the screen container.
> 
> In `Wallet`, removes the bottom fade `LinearGradient` overlay and its
associated scroll/size tracking state, simplifying scroll handling to
just notify homepage section subscribers via `handleHomepageScroll`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c4b0e41. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[3c1ee48](3c1ee48)

Co-authored-by: Brian August Nguyen <brianacnguyen@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**
Increase JS bundle 1 MB
<!--
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**

<!-- [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]
> **Low Risk**
> Low risk: workflow-only change that just relaxes the CI bundle-size
gate by 1 unit and doesn’t affect runtime code.
> 
> **Overview**
> **CI bundle-size gating has been relaxed slightly.** The
`js-bundle-size-check` step in `.github/workflows/ci.yml` now allows an
iOS `main.jsbundle` size threshold of `53` instead of `52` when running
`./scripts/js-bundle-stats.sh`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3c0f0a4. 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**
OTA was broken with old environment variables check. This PR aims to
solve that by introdocing a new environment variable.

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

<!-- [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**
> Changes how several services choose API endpoints/environments by
switching from `GITHUB_ACTIONS`/`E2E` checks to a new
`BUILDS_ENABLED_WITH_GH_ACTIONS_TEMPORARY` flag, which could route
builds to different backend environments if misconfigured.
> 
> **Overview**
> Introduces a new build-time env flag,
`BUILDS_ENABLED_WITH_GH_ACTIONS_TEMPORARY`, and uses it to decide when
to take **build-provided** URLs/environments (from `builds.yml`) versus
deriving them from `METAMASK_ENVIRONMENT`.
> 
> Updates Baanx Card URL mapping, ramps SDK environment selection
(Aggregator + Deposit), ramps controller init, and rewards API URL
override logic to key off this flag, and refreshes/adjusts tests
accordingly (including removing the previous special-casing tied to
`E2E`).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
4249918. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
The encryptorAdapter introduced in PR #26258 overrides encryptWithKey to
return browser-passworder format ({ data }) instead of the mobile Encryptor
format ({ cipher }). However, decrypt and decryptWithDetail were not
overridden — they were spread from the mobile Encryptor, which reads the
cipher field. This caused a crash on the next unlock after any background
JWT token refresh:

  TypeError: The first argument must be one of type string, Buffer...
  Received type undefined (quick-crypto.ts:101)

Fix: add normalizeVaultFormat which injects cipher = data when a vault has
data but no cipher, and override decrypt and decryptWithDetail in the
adapter to normalize before delegating to the underlying Encryptor.

Also harden decryptWithKey to accept both data and cipher fields (for
pre-adapter vaults that only carry cipher), and throw explicitly when
both fields are absent.

Adds end-to-end tests that reproduce the bug scenario: background token
refresh writes a data-format vault via encryptWithKey, then decrypt /
decryptWithDetail must recover it on the next unlock.
…r with safeareaview (#27502)

- fix: Updated root pages scrollable behavior with safeareaview
cp-7.69.1 cp-7.70.0 (#27446)

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

Standardizes safe area and header inset behavior across the main tab
views (Wallet, Explore, Activity, Rewards).

1. **Reason for the change:** These views used `edges={{ bottom:
'additive' }}` on `SafeAreaView` and `includesTopInset` on headers,
which was inconsistent with the desired layout and could cause double
insets or incorrect safe area handling.
2. **Improvement:** Switched to `edges={{ top: 'additive' }}` on
`SafeAreaView` and removed `includesTopInset` from header components so
the top safe area is handled by the screen container and headers align
consistently.

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

## **Manual testing steps**

```gherkin
Feature: Safe area and header insets on main tabs

  Scenario: Wallet, Explore, Activity, and Rewards use consistent safe area
    Given the app is open on a device or simulator with a notch/safe area

    When the user switches to each main tab (Wallet, Explore, Activity, Rewards)
    Then the top safe area is applied by the screen (no double inset)
    And the header (title + accessories) aligns correctly below the safe area
    And the bottom of each view respects the tab bar / device safe area as before
```

## **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/0eda5978-7bd5-4428-86ea-f62637fb06ed


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

### **After**



https://github.com/user-attachments/assets/a8ff8e19-a49e-41f4-9056-7c2271da8c66


<!-- [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**
> Layout-only changes to core tab screens
(Wallet/Explore/Activity/Rewards) that can affect safe-area padding and
scroll behavior across devices, plus removal of Wallet’s bottom
fade/scroll tracking logic which could subtly change UX on the homepage.
> 
> **Overview**
> Standardizes safe-area handling across the main tab views by switching
root `SafeAreaView` usage from `edges={{ bottom: 'additive' }}` to
`edges={{ top: 'additive' }}` and removing header `includesTopInset` so
the top inset is applied consistently by the screen container.
> 
> In `Wallet`, removes the bottom fade `LinearGradient` overlay and its
associated scroll/size tracking state, simplifying scroll handling to
just notify homepage section subscribers via `handleHomepageScroll`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c4b0e41. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[3c1ee48](3c1ee48)

Co-authored-by: Brian August Nguyen <brianacnguyen@gmail.com>
Co-authored-by: João Loureiro <175489935+joaoloureirop@users.noreply.github.com>
Resolved conflicts between stable (7.69.0) and release/7.68.3:

Build/version: take release/7.68.3 versions
- app/constants/ota.ts: keep v7.68.3

Source code: take release/7.68.3 (hotfix-specific changes)
- remote-feature-flag-build-time-defaults-config.ts: keep (deleted on stable)
- featureFlagController selectors: keep release/7.68.3 versions

Merge with "Create a merge commit" — do NOT squash.

Made-with: Cursor
…70.0 (#27498)

- chore: Market Insights design review cp-7.70.0 (#27259)

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

Updates a few design elements In Market Insights.

## **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 new Buy navigation and CAIP-asset parsing from Market Insights,
plus a `react-native-video` background; these touch navigation/asset-id
construction and could break CTAs or tests if ramp/swap inputs are
wrong.
> 
> **Overview**
> Updates the Market Insights full-screen view to include an
auto-playing light/dark background video and replaces the single Trade
CTA with side-by-side **Swap** and **Buy** buttons. Swap interaction
tracking is renamed from `trade` to `swap`, and a new `buy` interaction
event is tracked; Buy routes through ramp navigation with best-effort
`assetId` derivation from the token address/chain.
> 
> Polishes several Market Insights components/styles (entry card
header/disclaimer layout, icon sizing, feedback copy/typography, bottom
sheet source list spacing) and tweaks behavior so tapping a source
closes the trend sources sheet. Tests and Jest config are updated
accordingly, including new mocks for `.mp4` assets and
`react-native-video`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d1e6ce2. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[dab238f](dab238f)

Co-authored-by: António Regadas <antonio.regadas@consensys.net>
…allet token list cp-7.69.1 cp-7.70.0 (#27503)

- chore: correct token price formatting in wallet token list cp-7.69.1
cp-7.70.0 (#27485)

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

Two visual bugs were affecting the token price display in the wallet
token list (`TokenListItemV2`) and the explore/trending page.

**Bug 1 — Missing thousand-separator commas**
The token price in the second row of each list item (e.g. `$2283.65` for
ETH) was formatted with `addCurrencySymbol`, which constructs the string
via a plain `.toString()` call and never applies locale-aware number
formatting. This meant that prices ≥ $1,000 rendered without commas
(e.g. `$2283.65` instead of `$2,283.65`).

Fixed by switching to `formatPriceWithSubscriptNotation`, the same
formatter already used on the asset-overview/price chart page, which
uses `Intl.NumberFormat('en-US', …)` and produces properly
comma-separated output.

**Bug 2 — Too many decimal places for large prices**
`formatPriceWithSubscriptNotation` was configured with
`maximumFractionDigits: 4` unconditionally, so a price like `$2,285.013`
(3 significant decimal digits within the allowed 2–4 range) rendered
incorrectly. This also affected the explore/trending token row.

Fixed by scoping `maximumFractionDigits` to the magnitude of the price:
2 decimals for values ≥ 1, 4 decimals for values < 1 (where extra
precision matters, e.g. `$0.1446`). Subscript notation for very small
values is unaffected.

**Bug 3 — Unintentional bold weight on fiat balance**
The fiat balance text variant was `BodyMDBold` instead of
`BodyMDMedium`, making the balance appear heavier than intended.

The full description has been saved to
`.agent/chore-remove-bold-and-add-commas-list-item-v2.PR-desc.md`.
<!--
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: fixed token prices in the wallet list displaying
without thousand-separator commas and with too many decimal places

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-2909 &
https://consensyssoftware.atlassian.net/browse/ASSETS-2921

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

<img width="200" alt="image"

src="https://github.com/user-attachments/assets/3916037a-33b4-4e7e-8fbe-1dd033256037"
/>

<img width="200" alt="image"

src="https://github.com/user-attachments/assets/84efa704-d986-4e2d-95f2-d277906975df"
/>


### **After**
Look at the title and the USD amount. As you can see it is not bold
anymore:

<img width="200" alt="image"

src="https://github.com/user-attachments/assets/3a267238-9137-4849-9961-fc1af621b384"
/>

Look at the decimals in Ethereum on Mainnet:

<img width="200" alt="image"

src="https://github.com/user-attachments/assets/c4275147-836d-4446-9ce4-f2b9b46b31ef"
/>


<!-- [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**
> Adjusts a shared price formatter and switches wallet token list
rendering to it, which could change how fiat prices appear across
multiple screens. Risk is limited to display/formatting (no transaction
or balance calculations).
> 
> **Overview**
> Fixes token price display in the wallet token list by replacing
`addCurrencySymbol` with `formatPriceWithSubscriptNotation`, restoring
locale-aware formatting (e.g., thousand separators) and consistent
currency symbol/suffix handling.
> 
> Updates `formatPriceWithSubscriptNotation` to **cap decimals at 2 for
values >= 1** while keeping up to 4 decimals (and subscript notation)
for smaller values, and adds unit tests to cover the new truncation
behavior. Also tweaks the fiat balance text style in `TokenListItemV2`
from bold to a medium weight.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
18f74fe. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[af384ae](af384ae)

Co-authored-by: Juanmi <95381763+juanmigdr@users.noreply.github.com>
…Action cp-7.70.0 (#27497)

- chore: New Crowdin translations by Github Action cp-7.70.0 (#27390)

Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
[0050742](0050742)

Co-authored-by: MetaMask Bot <37885440+metamaskbot@users.noreply.github.com>
Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
metamaskbot and others added 27 commits March 19, 2026 16:44
This PR updates the change log for 7.70.0.

---------

Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
Co-authored-by: chloeYue <chloe.gao@consensys.net>
)

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

WebView JS dialogs (alert/confirm/prompt) were only suppressed for
inactive tabs, but could still appear on top of modals or other screens
drawn over the browser.

This adds useIsFocused to gate dialog visibility on both tab state and
screen focus, so dialogs are suppressed whenever the browser screen is
not in the foreground.

See recordings and notice that *After* does not show the alert on top of
the confirmation screen

(Seems that GitHub trimmed the video to 8 seconds. The original length
is 16 seconds.)


## **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: supress js dialogs when page is not focused

## **Related issues**

Fixes: MetaMask/mobile-planning#2312

## **Manual testing steps**

See issue linked above

## **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/0e72ccc9-123b-48a8-b4f5-6adee5ca2747

### **After**


https://github.com/user-attachments/assets/a24e0934-75df-437e-9e1f-72211a2baa0e

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

Migrated `Button` to DSRN package usage.

## **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/DSYS-445

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


https://github.com/user-attachments/assets/25c07e5d-4419-49d6-a8fe-e488a31f1605

### **After**


https://github.com/user-attachments/assets/1f90310e-02c5-47f9-8dc9-35dcae15974f

## **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 component migration limited to button props/styling; main
risk is minor visual/behavior differences in the new `Button`
implementation.
> 
> **Overview**
> Updates `SmartTransactionStatus` to use
`@metamask/design-system-react-native` `Button`/`ButtonVariant` instead
of the legacy component-library button.
> 
> Adjusts button usage to the new API (children text + `isFullWidth`
rather than `label` + custom width style), removing the now-unneeded
`styles.button` rule.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
394d3b5. 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**

Fixes an order details UI bug where the title for bank transfer details
was displaying for non bank-transfer orders.

[TRAM 3359](https://consensyssoftware.atlassian.net/browse/TRAM-3359)

<!--
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: fixes an order details UI bug

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

### *
<img width="458" height="974" alt="Screenshot 2026-03-20 at 10 03 02 AM"
src="https://github.com/user-attachments/assets/4d94ca14-1e17-401d-945b-5f38acf28e4a"
/>
*Before**

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

### **After**

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

<img width="451" height="976" alt="Screenshot 2026-03-20 at 11 39 11 AM"
src="https://github.com/user-attachments/assets/19595c85-e138-4fdc-bb52-a57271593ff8"
/>


## **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 UI-only change that gates rendering of the bank details
section; main risk is unintentionally hiding bank details if upstream
field names/structure change.
> 
> **Overview**
> Fixes an order details UI bug where the bank-transfer section header
could render for non-bank-transfer orders.
> 
> `OrderContent` now returns `null` for `bankDetailFields` unless at
least one expected bank detail field (e.g., amount, routing/account,
IBAN/BIC) is present, and tests add coverage for
absent/empty/non-matching `paymentDetails` vs. bank-transfer/SEPA
scenarios.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
65f6cfc. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…27778)

## **Description**

On a fresh install, `RemoteFeatureFlagController` loads flags
asynchronously while Engine builds controllers. `rampsControllerInit`
previously read the unified buy V2 flag only once; if flags were not in
state yet, `RampsController.init()` never ran, so buy token lists stayed
empty until a full app restart.

This change subscribes to `RemoteFeatureFlagController:stateChange`
(already delegated on `RampsControllerInitMessenger`) and re-runs the
same V2 startup path when remote flag state updates. Order-status
subscriptions are registered at most once. `RampsController.init()`
remains idempotent for repeated calls.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TRAM-3350

## **Manual testing steps**

```gherkin
Feature: Unified buy V2 after fresh install

  Scenario: Buy token list loads without restarting the app
    Given a dev build with unified buy V2 enabled via remote flags
    And the app is installed fresh (or remote flag cache cleared)

    When the user completes onboarding and opens Buy / token selection
    Then tokens and providers load without requiring an app restart
```

## **Screenshots/Recordings**

<div>
<a href="https://www.loom.com/share/e80a3794612d4030aa963834e5a8d7bf">
<p>Fix Ramps controller not initializing on fresh install - Watch
Video</p>
    </a>
<a href="https://www.loom.com/share/e80a3794612d4030aa963834e5a8d7bf">
<img style="max-width:300px;"
src="https://cdn.loom.com/sessions/thumbnails/e80a3794612d4030aa963834e5a8d7bf-13202ae1a2494608-full-play.gif#t=0.1">
    </a>
  </div>

### **Before**

### **After**

## **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 a new subscription-driven initialization path triggered by
`RemoteFeatureFlagController:stateChange`, which can change startup
behavior and potentially cause repeated init/polling if underlying
idempotency assumptions are wrong.
> 
> **Overview**
> Ensures Unified Buy V2 startup runs even when remote feature flags
hydrate *after* Engine/controller initialization by subscribing to
`RemoteFeatureFlagController:stateChange` and re-checking the V2 flag.
> 
> Refactors V2 startup into a helper that conditionally calls
`RampsController.init()`/`startOrderPolling()` and registers
order-status subscriptions only once. Updates tests to cover the “flag
off at startup then enabled on stateChange” scenario and to include
`subscribe` in the thrown-state mock.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
78ff800. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…27794)

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

The root messenger on mobile does not currently have a
`captureException` function passed. This means that any controllers
relying on `messenger.captureException` to record unhandled errors are
having their errors swallowed. This PR fixes it by passing in the Sentry
`captureException` function.

## **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 an issue where certain error reporting would not
work

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: wires existing Sentry `captureException` into root
`Messenger`/`ExtendedMessenger` construction; behavior change is limited
to enabling error capture for controllers that opt into it.
> 
> **Overview**
> Fixes missing error reporting on mobile by importing Sentry’s
`captureException` and passing it into both `getRootExtendedMessenger`
and `getRootMessenger` in `app/core/Engine/types.ts`.
> 
> This ensures controllers using `messenger.captureException` can
forward unhandled errors to Sentry instead of silently swallowing them.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1617775. 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**

Updates both arrows to the correct sizes.
Updates ai ctrl package to latest version.

<img width="341" height="115" alt="Screenshot 2026-03-23 at 10 42 27"
src="https://github.com/user-attachments/assets/ddef0cf0-b30b-435c-8e41-047f038903dc"
/>

<img width="361" height="104" alt="Screenshot 2026-03-23 at 10 42 38"
src="https://github.com/user-attachments/assets/5ca7fb19-39bb-4b5a-b964-15ca894367c4"
/>

## **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]
> **Low Risk**
> Low risk UI-only change that swaps arrow icons to the design-system
`ButtonIcon` for consistent sizing and styling, with minimal layout
tweaks.
> 
> **Overview**
> Updates the Market Insights UI to use the design-system `ButtonIcon`
for both the back arrow in `MarketInsightsViewHeader` and the trailing
arrow in `MarketInsightsEntryCard`, aligning icon sizing/styling with
the design system.
> 
> Includes small layout adjustments (e.g., header padding and spacing)
and wraps the entry-card arrow in a non-interactive container
(`pointerEvents="none"`) to preserve the card’s press behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6e137b5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
# 🚀 v7.70.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
- [x] Accounts Framework
- [x] Assets
- [x] Bots Team
- [x] Card
- [x] Confirmations
- [x] Core Extension UX
- [x] Core Platform
- [x] Design System
- [x] Earn
- [x] Engagement
- [x] Mobile Platform
- [x] Mobile UX
- [x] Networks
- [x] Onboarding
- [x] Perps
- [x] Predict
- [x] Ramp
- [x] Rewards
- [x] Social & AI
- [x] Swaps and Bridge
- [x] team-ramps
- [x] 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
- Testing plan sheet -
https://docs.google.com/spreadsheets/d/1tsoodlAlyvEUpkkcNcbZ4PM9HuC9cEM80RZeoVv5OCQ/edit?gid=404070372#gid=404070372
…ble cp-7.71.0 (#27756)

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

"0 ETH" was displayed on some order pages when the order info was not
yet available. This bug fixes by adding "..." placeholder until the info
arrives.

[TRAM-3360](https://consensyssoftware.atlassian.net/browse/TRAM-3360)

<!--
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: Fixes small UI issue with ramps orders

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

<img width="544" height="319" alt="Screenshot 2026-03-20 at 11 51 50 AM"
src="https://github.com/user-attachments/assets/cc2fd384-2c79-49c0-93fa-66b07192ffa6"
/>

<img width="436" height="933" alt="Screenshot 2026-03-20 at 11 53 40 AM"
src="https://github.com/user-attachments/assets/1d350708-6bfe-4fae-af10-80868d26914c"
/>


## **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**
> Adjusts order-details loading/terminal-state logic and amount
formatting, which could change what users see for certain pending/failed
orders; impact is limited to UI display and snapshots.
> 
> **Overview**
> Prevents ramps order UIs from showing `0 ETH`/`0` amounts when data
hasn’t arrived by treating `0`/missing `cryptoAmount` (and related fiat
fields) as **unknown** and rendering an `...` placeholder in both the
orders list (`displayOrder`) and order details (`OrderContent`).
> 
> Order details now distinguishes *loading* vs *terminal* statuses
(e.g., `Failed`, `Cancelled`) so terminal orders without amounts render
placeholders instead of skeleton loaders, and fiat `fees`/`total`
formatting is switched to `formatWithThreshold` currency formatting
(snapshot updates included).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a9bc072. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
## **Description**

Remove outdated confirmations documentation files.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

## **Manual testing steps**

## **Screenshots/Recordings**

### **Before**

### **After**

## **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 documentation-only change; main risk is broken internal doc
links (e.g., references to removed `docs/confirmations.md`).
> 
> **Overview**
> Removes several outdated confirmation-related docs, including the
confirmation refactoring READMEs and the `docs/confirmations.md` guide.
> 
> No runtime code changes; reviewers should verify any remaining
documentation links aren’t now pointing at the deleted files.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0759b1c. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This PR syncs the stable branch to main for version 7.72.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.72.0
…fetch (#27682)

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

## **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**
> Moderate risk due to upgrading `@metamask/assets-controller` to a new
major version and changing init-time instrumentation; could affect
controller initialization behavior or observability if the new `trace`
hook contract differs.
> 
> **Overview**
> Switches `assetsControllerInit` instrumentation from MetaMetrics event
emission to passing a Sentry-backed `trace` function into
`AssetsController`, removing the custom `trackMetaMetricsEvent`
builder/call.
> 
> Updates unit tests to assert the new `trace` option, and bumps
dependencies to `@metamask/assets-controller@^3.0.0` and
`@metamask/core-backend@^6.2.0` (with corresponding `yarn.lock`
changes).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b6dadbf. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Removes the `release-pr-approval.yml` workflow that required Release
Team approval on PRs targeting `Version-v*` and `release/*` branches.
This change is part of replacing that mechanism (INFRA-3396).

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: CI workflow removal

  Scenario: No app behavior change
    Given the release PR approval workflow is removed
    When CI runs on this PR
    Then checks should not depend on that workflow
```

## **Screenshots/Recordings**

### **Before**

N/A — internal CI only.

### **After**

N/A — internal CI only.

## **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.
<!--
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 work is part of removing the tokensChainsCache entirely**

The useERC20Tokens hook was the sole internal consumer of
selectTokenListArray and was only called in useDisplayName. I have
updated the hook to resolve this metadata using the /assets/v3 endpoint
(which caches data and is very performant)

<!--
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: modified useERC20Tokens to make an API call instead of
reading from the cache

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-2954

## **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/675f7402-e418-4bb4-85f3-048102c89ff9

<!-- [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**
> Introduces a new client-side token-metadata fetch/caching layer and
shifts `useERC20Tokens` from Redux cache reads to network-backed data,
which could affect confirmations display names/images and add runtime
dependency on the tokens API.
> 
> **Overview**
> Updates `useERC20Tokens` to stop reading ERC-20 metadata from
`tokensChainsCache` and instead resolve names/symbols/icons via a new
`useTokensData` hook backed by the tokens API `v3/assets` endpoint
(using CAIP-19 asset IDs).
> 
> Adds `buildEvmCaip19AssetId` for consistent lowercased asset ID
construction, plus a batched/deduped module-level cache in
`useTokensData` (25 IDs per request, shared in-flight promises). Tests
are rewritten/added accordingly, CODEOWNERS is updated for the new hook,
and E2E token API mocks now include the new v3 endpoint.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
4d2eace. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Use the actual GeolocationController state instead of rewards Redux
state to determine mUSD card visibility on the Rewards dashboard. This
prevents a flash of the mUSD card for UK users when the card slice loads
before the geo check completes.

**Problem:**
Previously, `showMusdCard` was derived as `optinAllowedForGeo !==
false`, treating `null` (initial/undetermined) the same as `true`
(allowed). The rewards Redux initial state has
`optinAllowedForGeoLoading: false` and `optinAllowedForGeo: null`. When
the card slice had already loaded but the rewards geo check hadn't
started yet, `isAnyGeoLoading` evaluated to `false` while `showMusdCard`
was `true`, causing the mUSD card to render briefly for UK users.

**Solution:**
- Use `selectGeolocationLocation` and `selectGeolocationStatus` from
GeolocationController
- Require positive geo confirmation: location must be defined, not
'UNKNOWN', and not 'GB'
- Handle all geo status states: 'idle', 'loading', 'complete', 'error'
- Add `UK_COUNTRY_CODE` and `UNKNOWN_LOCATION` constants for clarity

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: mUSD card geo restriction

  Scenario: UK user should not see mUSD card flash
    Given the user is in the UK (geoLocation is 'GB')
    And the card geo check has completed before the GeolocationController

    When user navigates to Rewards dashboard
    Then the mUSD calculator card should NOT flash briefly
    And the mUSD calculator card should remain hidden

  Scenario: Non-UK user sees mUSD card after geo check completes
    Given the user is in the US (geoLocation is 'US')

    When user navigates to Rewards dashboard
    And the GeolocationController status becomes 'complete'
    Then the mUSD calculator card should be visible
```

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


Made with [Cursor](https://cursor.com)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UI gating change that only affects when the mUSD rewards card
renders; main risk is inadvertently hiding/showing the card for some
geolocation edge cases (e.g., undefined/UNKNOWN/status handling).
> 
> **Overview**
> Updates the Rewards dashboard `EarnRewardsPreview` to derive mUSD card
visibility from `GeolocationController`
(`selectGeolocationLocation`/`selectGeolocationStatus`) instead of the
rewards reducer’s `optinAllowedForGeo` flags.
> 
> The mUSD card now renders *only* after a confirmed, known location and
is explicitly hidden for `GB` and `UNKNOWN`/`undefined` locations,
treating `idle`/`loading` as a loading state to prevent a brief “flash”
for UK users. Tests are updated to cover the new `idle`/`loading`
skeleton behavior and the `undefined`/`UNKNOWN`/`GB` hiding cases.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b466bbf. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **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?
-->

`TooltipModal` was using legacy component-library patterns
(`StyleSheet.create`, raw `View`, deprecated `BottomSheetFooter`, and
component-library `Text`) that are no longer consistent with the current
UI development standards.

This PR migrates `TooltipModal` to fully conform to the new standards:

- Replaces `View` with `Box` from `@metamask/design-system-react-native`
- Replaces component-library `Text`/`TextVariant`/`TextColor` with the
design system equivalents (`TextVariant.BodyMd`,
`TextColor.TextAlternative`)
- Replaces the deprecated component-library `BottomSheetFooter` (which
used a broken `Object.assign` + `StyleSheet.create` approach for style
overrides) with the design system `BottomSheetFooter`, which applies
styles via a style array and `twClassName` correctly
- Removes `StyleSheet.create` and the companion `ToolTipModal.styles.ts`
file
- Adds `useSafeAreaInsets` for device-aware bottom padding on the footer
- Adds `useTailwind` for all Tailwind-based styling
- Updates tests to match the new component structure

The deprecated `BottomSheetFooter` had a bug where passing
`paddingHorizontal` via its `style` prop did not apply correctly — the
internal `Object.assign` + `StyleSheet.create` merge caused the
shorthand `paddingHorizontal` to be overridden by already-resolved
longhand values. The design system component resolves this by applying
styles as a proper array where the last entry wins.

## **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/SWAPS-4249

## **Manual testing steps**

```gherkin
Feature: TooltipModal rendering and interaction

  Background:
    Given I am logged into MetaMask Mobile

  Scenario: user opens a tooltip and reads content
    Given I am on a screen that displays a tooltip icon (e.g. Swaps confirmation — Slippage row)

    When user taps the info icon next to a label
    Then a bottom sheet should appear with the correct title in the header
    And the tooltip content text should be visible below the header
    And the "Got it" button should be visible in the footer with 16px horizontal padding
    And on devices with a home indicator (iPhone X+) the button should sit above the home bar

  Scenario: user dismisses tooltip via "Got it" button
    Given the tooltip bottom sheet is open

    When user taps the "Got it" button
    Then the bottom sheet should close

  Scenario: user dismisses tooltip via close icon
    Given the tooltip bottom sheet is open

    When user taps the X icon in the header
    Then the bottom sheet should close

  Scenario: tooltip with optional footer text
    Given a tooltip is configured with additional footer text

    When user opens the tooltip
    Then the footer text should appear below the "Got it" button
    And the footer text should respect the safe area bottom inset
```

## **Screenshots/Recordings**

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

### **Before**

N/A

### **After**

<img width="1184" height="852" alt="εικόνα"
src="https://github.com/user-attachments/assets/0f338660-24f3-4150-8cb6-0dcf8bdcd3d0"
/>


## **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**
> Moderate risk because it changes `TooltipModal`’s component
implementation and removes the `bottomPadding` navigation/typing option,
which could affect any callers relying on that param or footer spacing
behavior.
> 
> **Overview**
> Migrates `TooltipModal` to the MetaMask design system by replacing
legacy `View`/`StyleSheet` styling and the deprecated component-library
footer with `Box`, design-system `Text`, and design-system
`BottomSheetFooter` using Tailwind (`useTailwind`).
> 
> Updates footer spacing to use `useSafeAreaInsets` for bottom padding
and removes the custom `bottomPadding` route param/options plumbing
end-to-end (`ToolTipModal.types.ts`, `useTooltipModal`, `KeyValueRow`
tooltip types/usage, and related tests), deleting
`ToolTipModal.styles.ts` and adjusting snapshots/mocks accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
66dbdb8. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…w system (#27775)

## **Description**

Adds a **deterministic recipe system** for agentic validation of the
perps feature. Recipes are JSON files that describe step-by-step app
interactions (navigate, press, type, assert) — executed against a
running app via CDP. They replace manual testing with reproducible,
token-efficient automation.

### Why recipes?

**For agents doing PR review or bug fixing:** An agent can generate a
recipe that opens a position, sets TP/SL, closes it — and record the
execution as video evidence. One JSON file replaces dozens of CDP tool
calls, saving inference tokens and producing consistent results.

**For developers working with agents on features (recipe-driven
development):** Write the recipe first — define expected navigation,
interactions, and assertions — then implement the feature until the
recipe passes. Like TDD but for agent workflows: define the expected
output, iterate until green, get a fully reproducible validation
artifact. Existing Gherkin scenarios from PRs can be directly migrated
to recipes with 1:1 step mapping.

**Composability via `flow_ref`:** Common operations (open position,
create TP/SL, close position) are packaged as reusable flows. A recipe
composes flows instead of repeating raw steps — 4 lines of `flow_ref`
replace 40 lines of navigate/press/wait.

### What's in this PR

- **12 parameterized flows** — `trade-open-market`,
`trade-close-position`, `tpsl-create`, `tpsl-edit`, `order-limit-place`,
`order-limit-cancel`, `position-add-margin`, `market-discovery`,
`market-watchlist`, `activity-view`, `select-account`, `setup-testnet`
- **`validate-recipe.sh`** — recipe runner with `flow_ref` composition,
`wait_for` condition polling, HUD overlay, pre-condition checks,
`{{param}}` templating
- **`wait_for` action** — condition-based polling replacing all blind
`wait` steps (route, testID visibility, or arbitrary expression)
- **testID additions** — keypad keys, tab bars, order view buttons,
market header — enabling recipe-driven navigation without coordinates
- **`AgentStepHud`** — `__DEV__`-only overlay showing current step ID
during recipe execution
- **Team directory structure** (`teams/<team>/flows/`, `evals/`,
`recipes/`, `pre-conditions.js`)

### Lifecycle recipe (used for validation video)

This recipe composes 4 flows to validate a complete trade lifecycle —
the exact JSON that `validate-recipe.sh` executes
(`teams/perps/recipes/full-trade-lifecycle.json`):

```json
{
  "title": "Full BTC trade lifecycle — mainnet start, testnet switch, open, TP/SL, close",
  "validate": {
    "runtime": {
      "steps": [
        { "id": "nav-wallet-home", "action": "navigate", "target": "WalletView" },
        { "id": "switch-mainnet", "action": "toggle_testnet", "enabled": false },
        { "id": "wait-mainnet", "action": "wait_for",
          "expression": "JSON.stringify({isTestnet:Engine.context.PerpsController.state.isTestnet})",
          "assert": { "operator": "eq", "field": "isTestnet", "value": false } },
        { "id": "nav-perps-home", "action": "navigate", "target": "PerpsHomeView" },
        { "id": "wait-perps-home", "action": "wait_for", "route": "PerpsMarketListView" },
        { "id": "ensure-testnet", "action": "flow_ref", "ref": "setup-testnet" },
        { "id": "verify-provider", "action": "eval_ref", "ref": "providers",
          "assert": { "operator": "contains", "value": "hyperliquid" } },
        { "id": "open-long-btc", "action": "flow_ref", "ref": "trade-open-market",
          "params": { "symbol": "BTC", "side": "long", "usdAmount": "10", "leverage": "2" } },
        { "id": "wait-position", "action": "wait_for", "timeout_ms": 10000,
          "expression": "...",
          "assert": { "operator": "eq", "field": "found", "value": true } },
        { "id": "create-tpsl", "action": "flow_ref", "ref": "tpsl-create",
          "params": { "symbol": "BTC" } },
        { "id": "close-position", "action": "flow_ref", "ref": "trade-close-position",
          "params": { "symbol": "BTC" } },
        { "id": "wait-closed", "action": "wait_for", "timeout_ms": 10000,
          "expression": "...",
          "assert": { "operator": "eq", "field": "found", "value": false } }
      ]
    }
  }
}
```

**Result:** 14/14 steps pass, composing 4 nested flows (34 total steps
across flows).

### Risk profile

Shell scripts + JSON schemas — dev-only tooling, not shipped in
production builds. React component changes limited to adding `testID`
props (no logic changes). `AgentStepHud.tsx` gated behind `__DEV__`.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Internal perps agentic tooling — no external ticket.

## **Manual testing steps**

```gherkin
Feature: Agentic recipe validation

  Scenario: Full trade lifecycle via recipe runner
    Given Metro and CDP bridge are connected to a running app
    And wallet is unlocked with testnet-capable account
    When developer runs: bash scripts/perps/agentic/validate-recipe.sh scripts/perps/agentic/teams/perps/recipes/full-trade-lifecycle.json
    Then recipe switches to testnet, opens BTC long, creates TP/SL, closes position
    And all 14 top-level steps pass (composing 4 nested flow_refs)
    And HUD overlay shows current step ID on screen during execution

  Scenario: Dry-run validates JSON without app
    When developer runs with --dry-run flag
    Then all steps are parsed and resolved without executing against the app
```

## **Screenshots/Recordings**

### **Before**

N/A — new tooling, no prior state.

### **After**



https://github.com/user-attachments/assets/68ed3a0a-e79c-4cae-a331-823c16b6ed33


## **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**
> Mostly adds/renames `testID` props across Keypad, Tabs, and Perps UI
plus a `__DEV__`-only HUD overlay; behavior changes are minimal and
largely test/automation-facing.
> 
> **Overview**
> Improves agentic/E2E automation hooks by adding **stable `testID`s**
across shared UI (`Keypad`, `Tabs`) and many Perps surfaces (order rows,
TP/SL inputs, limit price sheet, adjust margin actions, transactions
tabs, and various touchable rows/buttons), including fixing a mislabeled
`TAKE_PROFIT_BUTTON` selector.
> 
> Adds a **dev-only** `AgentStepHud` overlay to `App` (rendered only in
`__DEV__`) to display the currently executing agent step, and updates
Perps tests/snapshots to match the new identifiers. Also updates
CODEOWNERS for `scripts/perps/agentic/teams/perps/` and ignores local
`.task/` working directories.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a568618. 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**

Fix gasless support check in hook useAutomaticGasFeeTokenSelect

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

## **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="396" height="847" alt="Screenshot 2026-03-19 at 4 18 39 PM"
src="https://github.com/user-attachments/assets/882e1bd4-486d-40f9-aeee-22c4a09f9987"
/>

## **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: a small conditional change in a confirmation hook that only
affects when a gas fee token is auto-selected, with no new data flows or
security-sensitive logic.
> 
> **Overview**
> Fixes `useAutomaticGasFeeTokenSelect` so it only auto-selects a
non-native gas fee token when **gasless is actually supported**
(`isSupported` from `useIsGaslessSupported`), instead of triggering
based solely on `isSmartTransaction`/insufficient balance state.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f6cbc58. 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**

Extend predict withdraw e2e test. This test was generated with the
e2e-test skill

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

<!-- [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**
> Primarily affects Detox E2E infrastructure by changing shared default
mocks and Polymarket RPC/TX-sentinel behavior, which could cause
unrelated tests to start/stop matching mocks. No production app logic
changes, but the mocking surface area is broad and network/transaction
flows are easy to break.
> 
> **Overview**
> Adds a real Detox smoke test that **executes the Predict balance
withdraw flow end-to-end** (open Predict, tap Withdraw, enter amount,
confirm) using new page objects and selector text IDs for the Withdraw
button and activity label.
> 
> Extends E2E mocking to support Polygon Predict withdraw’s **EIP-7702
relay path**, including shared `TX_SENTINEL_NETWORKS_MAP` default
response, overrides to enable `relayTransactions` for Polygon, mocks for
`eth_sendRelayTransaction` + relay status polling, and fixes to Polygon
RPC mocks to return valid tx hashes/receipts and token metadata needed
for request validation.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
463f49e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Description

Test-only refactor to remove hard-coded hex colors from Earn/Stake test
suites and align with the `@metamask/design-tokens/color-no-hex` rule by
using the shared `mockTheme` and brand tokens. No production logic
changes.

- Earn withdrawal confirmation test now expects
`mockTheme.colors.background.alternative` to match production.
- `useMerklClaimStatus.test.ts` replaces hex values with
`mockTheme.colors.icon.default` and
`mockTheme.colors.background.default`.
- `GraphCursor.test.tsx` uses `mockTheme.brandColors.green600` instead
of a hex literal.
- ESLint: re-enabled `@metamask/design-tokens/color-no-hex` as `error`
for `app/components/UI/Earn/**/*` and `app/components/UI/Stake/**/*` to
keep these areas compliant going forward.

## Changelog

CHANGELOG entry: null

## Related issues

Split from #26651 to reduce CODEOWNERS fanout.

## Manual testing steps

```gherkin
Feature: Enforce design-token colors in Earn/Stake tests

  Scenario: Lint and unit tests succeed
    Given the repository is checked out on this branch
    When I run "yarn lint" and "yarn test:unit"
    Then lint passes without color-no-hex violations in Earn/Stake paths
     And unit tests pass
```

## Screenshots/Recordings

N/A

## Pre-merge author checklist

- [ ] I've followed MetaMask contributor guidelines and coding standards
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included/updated tests where applicable
- [ ] I've applied appropriate labels (internal maintainers)

<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-bd9a542d-02be-4d96-8eb9-16079680c303"><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-bd9a542d-02be-4d96-8eb9-16079680c303"><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>
#27814)

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

Adds two missing metric events to the Perps Market Details view to bring
it to parity with the token details flow. `MARKET_INSIGHTS_OPENED` now
fires whenever a user taps the Market Insights entry card, and
`PERPS_SCREEN_VIEWED` now includes a `market_insights_displayed` boolean
property that reflects whether a report was actually shown, with the
event held until the insights fetch resolves so the value is fully
accurate.

## **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]
> **Low Risk**
> Low risk: changes are limited to analytics instrumentation and event
timing gated on Market Insights loading, with added unit tests to
validate tracking and navigation behavior.
> 
> **Overview**
> Adds missing Market Insights instrumentation to the Perps market
details screen.
> 
> `PerpsMarketDetailsView` now fires
`MetaMetricsEvents.MARKET_INSIGHTS_OPENED` (with `perps_market`) when
the Market Insights entry card is tapped, and delays
`MetaMetricsEvents.PERPS_SCREEN_VIEWED` until insights loading completes
so it can include an accurate `market_insights_displayed` boolean.
> 
> Updates/extends `PerpsMarketDetailsView.test.tsx` with mocks for
`useMarketInsights`/feature flags and new tests covering the new
tracking payloads and navigation to `Routes.MARKET_INSIGHTS.VIEW` with
`isPerps: true`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
dc97116. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…27803)

## **Description**

Updates how the campaigns feature flag controls behavior on the Rewards
Dashboard:

- **Dashboard always renders** `CampaignsPreview` and
`EarnRewardsPreview` components regardless of feature flag state
- **Feature flag logic moved to `useRewardCampaigns` hook** - when
disabled:
  - Shows only upcoming campaigns (filtered by start date)
- Falls back to previous season campaigns if no upcoming campaigns exist
- **Campaign tiles become non-interactive when disabled** - users cannot
navigate to campaign details
- **Adds `fetchUpcomingOrPreviousSeasonCampaigns`** method to
RewardsController for the fallback logic

### Key Changes

| Before | After |
|--------|-------|
| Feature flag hides entire campaigns section | Always shows campaigns
section |
| N/A | When disabled: shows upcoming campaigns only |
| N/A | When disabled: falls back to previous season |
| All tiles navigable | Non-interactive tiles when flag disabled |

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

1. Enable campaigns feature flag → Full campaigns functionality
2. Disable campaigns feature flag → Only upcoming campaigns shown, tiles
non-interactive
3. Disable flag with no upcoming campaigns → Previous season campaigns
displayed

## **Screenshots/Recordings**

- Feature flag off: only show upcoming campaign as featured 
<img width="983" height="1958" alt="Screenshot from 2026-03-23 14-16-10"
src="https://github.com/user-attachments/assets/97c27a9d-0bfd-4fe7-b058-24d59fbf2652"
/>

- Feature flag off: tapping section or featured tile on rewards
dashboard leads to campaign overview page. Only previous season tile is
tappable

<img width="983" height="1958" alt="Screenshot from 2026-03-23 14-16-17"
src="https://github.com/user-attachments/assets/954d9a27-0a73-47c7-8c0d-029adc4a59eb"
/>

- Feature flag off: what would happen if no upcoming campaigns are
found, we can fallback to the previous season tile, which would take you
to the previous season summary if it/the section is tapped.

<img width="983" height="1958" alt="Screenshot from 2026-03-23 14-17-30"
src="https://github.com/user-attachments/assets/6618359a-f2cd-470b-b17a-9a00319c7f68"
/>

- If feature flag is on, then we will not filter on upcoming and allow
users to actually navigate to the campaign details page via campaign
tiles.

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs)
- [x] I've completed the PR template
- [x] I've included tests
- [x] I've documented any changes (if applicable)

## **Pre-merge reviewer checklist**

- [ ] I've verified the changes follow established patterns
- [ ] I've verified the test coverage is adequate

Made with [Cursor](https://cursor.com)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Moderate UI/behavior change around the campaigns feature flag that
alters what content is shown and which navigation paths are enabled;
risk is mainly regressions in campaign visibility and tap behavior when
the flag toggles.
> 
> **Overview**
> **Rewards dashboard now always renders** `CampaignsPreview` and
`EarnRewardsPreview`, removing the prior conditional/previous-season UI
paths (including the referral header action).
> 
> **Campaign feature flag behavior is pushed down into campaigns
components/hooks:** `useRewardCampaigns` always fetches campaigns when
subscribed but filters results to *upcoming-only* when the flag is off,
while `CampaignTile` adds `isInteractive`/`onPress` to disable deep-link
navigation and allow alternate navigation. `CampaignsPreview` adds a
no-campaigns fallback that shows `PreviousSeasonTile` and navigates to
`Routes.PREVIOUS_SEASON_VIEW`.
> 
> Tests were updated accordingly across `RewardsDashboard`,
`CampaignsPreview`, `CampaignTile`, `useRewardCampaigns`, and
`RewardsController` to reflect the new fetch/filtering and interactivity
rules.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9ca3bc0. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@pull pull Bot locked and limited conversation to collaborators Mar 23, 2026
@pull pull Bot added the ⤵️ pull label Mar 23, 2026
@pull pull Bot merged commit a4522a3 into Reality2byte:main Mar 23, 2026
3 of 36 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.