[pull] main from MetaMask:main#621
Merged
Merged
Conversation
…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 -->
Made-with: Cursor
…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>
This reverts commit 5cd8c23.
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>
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> <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> </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 -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 : )