Skip to content

release: 7.71.0#27708

Merged
chloeYue merged 212 commits into
stablefrom
release/7.71.0
Mar 27, 2026
Merged

release: 7.71.0#27708
chloeYue merged 212 commits into
stablefrom
release/7.71.0

Conversation

@metamaskbot
Copy link
Copy Markdown
Collaborator

@metamaskbot metamaskbot commented Mar 19, 2026

🚀 v7.71.0 Testing & Release Quality Process

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


📋 Key Processes

Testing Strategy

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

GitHub Signoff

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

Issue Resolution

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

Cherry-Picking Criteria

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

🗓️ Timeline and Milestones

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

✅ Signoff Checklist

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

Team sign-off checklist

  • Accounts Framework
  • Assets
  • Bots Team
  • Card
  • Confirmations
  • Core Platform
  • Design System
  • Earn
  • Mobile Platform
  • Mobile UX
  • Money Movement
  • Networks
  • Onboarding
  • Perps
  • Predict
  • Rewards
  • Social & AI
  • Swaps and Bridge
  • team-hardware-wallets
  • team-ramp
  • Transactions
  • Wallet Integrations

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

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

Many thanks in advance

Reference

Matt561 and others added 30 commits March 12, 2026 18:48
<!--
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 -->
## **Description**

Updated the following dependencies (with required integration work, if
any):

1. `@metamask/accounts-controller` - Update
`getInternalAccountByAddress` selector.
2. `@metamask/preferences-controller` - Update `PreferencesController`
state type.
3. `@metamask/account-tree-controller`
4.  `@metamask/delegation-controller`
5.  `@metamask/multichain-network-controller`
6. `@metamask/multichain-transactions-controller`

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: N/A

## **Manual testing steps**

1. Build from branch.
2. Create an account
3. Verify nothing breaks

## **Screenshots/Recordings**

N/A

## **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**
> Bumps multiple core controller dependencies and changes account lookup
to rely on the new `AccountsController.state.accountIdByAddress` map,
which could affect any code paths that resolve accounts by address if
the map is missing or stale.
> 
> **Overview**
> Updates several MetaMask core dependencies (notably
`@metamask/accounts-controller` to `37.0.0` and
`@metamask/account-tree-controller` to `5.x`).
> 
> Adopts the new `AccountsController` state field `accountIdByAddress`
by adding it to default/fixture state and updating
`getInternalAccountByAddress` to resolve accounts via this map (with
lowercase fallback) instead of scanning all accounts.
> 
> Adjusts tests, fixtures, and snapshots to include
`accountIdByAddress`, and updates migration test typings to reflect that
this field is non-persisted.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
bc2a1ab. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

This PR embed the metal card checkout flow into the Card
onboarding/sign-up flow.

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: embed the metal card checkout flow into the Card
onboarding/sign-up flow.

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


https://github.com/user-attachments/assets/776a82dc-b814-4dd1-96da-b902932c31cc

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes card onboarding navigation (including new `home` flow params
and StackActions replacement) and adds new UI/animation behavior, which
could affect user progression through card setup if eligibility logic or
routing params are wrong.
> 
> **Overview**
> Eligible US users who press **Enable Card** from `CardHome` are now
redirected to `Routes.CARD.CHOOSE_YOUR_CARD` (new `flow: 'home'`)
instead of always starting delegation/spending-limit setup; the route
passes through `shippingAddress` plus token/delegation/external wallet
context.
> 
> `ChooseYourCard` is updated to support the new `home` flow, adds a
swipe/peek affordance and an *upgrade-to-metal* link, refreshes
metal/virtual copy, and routes virtual-card selection into
`SPENDING_LIMIT` with `flow: 'manage'` and the forwarded params.
> 
> Post-order behavior changes so `OrderCompleted` uses
`StackActions.replace` to take onboarding users directly to
`SPENDING_LIMIT` (while upgrade users still go back to `CARD.HOME`), and
`SpendingLimit` now blocks back navigation during loading using a ref to
avoid stale listener state. Tests and English strings are updated
accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c52fcb5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

Removed unused mocks.

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

## **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="230" height="451" alt="image"
src="https://github.com/user-attachments/assets/295aa62b-a17e-42e7-ba3b-6fd8e52c5949"
/>

### **After**

<img width="230" height="451" alt="image"
src="https://github.com/user-attachments/assets/0a14d265-7cec-49d0-850f-82c2cfdba501"
/>

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Test-only change that removes redundant Jest mocks; low risk aside
from potentially reintroducing minor animation/timing differences in
affected tests.
> 
> **Overview**
> Removes the custom Jest mock for the `Skeleton` component from
`BridgeView.test.tsx` and `SwapsConfirmButton.test.tsx`, relying on the
real implementation during tests.
> 
> This cleans up unused test scaffolding in the Bridge/Swaps test suite
without changing production behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e94e5df. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Version Bump After Release

This PR bumps the main branch version from 7.70.0 to 7.71.0 after
cutting the release branch.

### Why this is needed:
- **Nightly builds**: Each nightly build needs to be one minor version
ahead of the current release candidate
- **Version conflicts**: Prevents conflicts between nightlies and
release candidates
- **Platform alignment**: Maintains version alignment between MetaMask
mobile and extension
- **Update systems**: Ensures nightlies are accepted by app stores and
browser update systems

### What changed:
- Version bumped from `7.70.0` to `7.71.0`
- Platform: `mobile`
- Files updated by `set-semvar-version.sh` script

### Next steps:
This PR should be **manually reviewed and merged by the release
manager** to maintain proper version flow.

### Related:
- Release version: 7.70.0
- Release branch: release/7.70.0
- Platform: mobile
- Test mode: false

---
*This PR was automatically created by the
`create-platform-release-pr.sh` script.*

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

## **Description**

Refactors the Perps Market Details screen to use the shared
`HeaderStandardAnimated` component instead of the custom
`PerpsMarketHeader` and navbar options, aligning with patterns used
elsewhere (e.g. Perps home, Token Details).

1. **Reason for the change:** Market Details used
`getPerpsMarketDetailsNavbar` (navigation.setOptions) and a custom
`PerpsMarketHeader` component; this was inconsistent with other screens
that use component-library header primitives and scroll-linked header
animation.
2. **Improvement:** Replaced `PerpsMarketHeader` with
`HeaderStandardAnimated`. Title is
`${getPerpsDisplaySymbol(market.symbol)}-USD`; subtitle is
`LivePriceHeader` (symbol, current price, throttle). Back button,
fullscreen (expand) and watchlist (star) actions are passed as
`endButtonIconProps`. Removed the navbar `useEffect`. Scroll content is
now an `Animated.ScrollView` with scroll passed to the header; a
`TitleSubpage` block at the top (token logo, title, leverage badge, and
`LivePriceHeader` as bottom accessory) drives the title section height
via `onLayout` and `useHeaderStandardAnimated`. `LivePriceHeader` text
variants were updated to `BodySM` and price color to `Alternative` for
the compact header context.

## **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/issues?jql=issueKey%20in%20(DSYS-555%2CDSYS-556%2CDSYS-557%2CDSYS-558)&selectedIssue=DSYS-558

## **Manual testing steps**

```gherkin
Feature: Perps Market Details header

  Scenario: Market Details shows animated header and title section
    Given the app is open and user has access to Perps

    When user opens a market (e.g. ETH-USD) from the Perps list
    Then the screen shows HeaderStandardAnimated with market title (e.g. "ETH-USD") and live price as subtitle
    And the header shows back button, fullscreen (expand) and watchlist (star) actions
    And the scroll area shows TitleSubpage with token logo, title, leverage badge, and live price
    When user scrolls the page
    Then the header animates (collapses/expands) in sync with scroll
    And chart, stats, and rest of content remain usable
```

## **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/eaf0e7ee-766a-4c84-8e48-7b7d9a897621

<!-- [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**
> Refactors the Perps Market Details header/navigation and scroll
handling, which could introduce UI regressions (collapsed header
behavior, button actions, layout) on a high-traffic trading screen. No
changes to trading/business logic or data handling.
> 
> **Overview**
> Refactors the Perps Market Details screen to use the shared
`HeaderStandardAnimated` pattern instead of the bespoke
`PerpsMarketHeader` and `navigation.setOptions` navbar configuration.
> 
> The header is now driven by `useHeaderStandardAnimated` and an
`Animated.ScrollView`, with a new top-of-page `TitleSubpage` section
(token logo, title, leverage badge, and live price) providing the
measured height for the collapse/expand animation; fullscreen and
watchlist actions are wired through header icon props.
> 
> Updates `HeaderStandardAnimated` to accept non-string
`title`/`subtitle` nodes, adjusts `LivePriceHeader` typography for the
compact header, removes the unused `getPerpsMarketDetailsNavbar`, and
extends Perps test IDs/tests to account for duplicated title rendering
(header + title section) and new price/change selectors.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0f37d84. 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**

Refactors multiple e2e page objects and flows to use the new
framework-agnostic element/gesture layer (EncapsulatedElementType,
UnifiedGestures, encapsulatedAction) so the same objects work under both
Detox and Appium/Playwright.

Adds/adjusts selector plumbing to support this migration, including new
localized selector text in
NetworkEducationModal/WalletActionsBottomSheet test IDs, swipe option
passthrough (speed, percentage) in UnifiedGestureOptions, and new
swap/bridge performance-test helpers in QuoteView (token testId
derivation, quote-visible assertion text, and network→chainId mapping).

## **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/MMQA-1563

## **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**
> Refactors a wide set of e2e page objects and selectors to a new
cross-framework abstraction, which can cause broad test failures if any
locator mapping is wrong. App runtime behavior is largely unchanged
aside from adding a few `testID`s used by automation.
> 
> **Overview**
> Updates e2e automation to use the framework-agnostic
`EncapsulatedElementType`/`UnifiedGestures`/`encapsulatedAction` APIs
across login, wallet, perps, networks, and swap/bridge page objects,
including replacing direct Detox elements with dual
Detox+Appium/Playwright locators.
> 
> Extends selector plumbing to support the migration: adds new localized
selector text constants, passes through swipe options (`speed`,
`percentage`) in unified gesture options, and adds swap/bridge helpers
(fee-disclaimer `testID`, token testId derivation, network→chainId
mapping, and quote-visibility assertions) to stabilize performance and
deeplink tests.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e474ab6. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ons (#27436)

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

## **Description**
This PR migrates the page objects used by `mm-connect` in the
performance tests to the new unified framework.

<!--
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: https://consensyssoftware.atlassian.net/browse/MMQA-1564

## **Manual testing steps**
N/A

## **Screenshots/Recordings**

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

### **Before**
N/A
<!-- [screenshots/recordings] -->

### **After**
N/A
<!-- [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**
> Moderate risk because it refactors shared E2E/performance test
infrastructure (driver utilities, visibility/wait options, and context
switching), which can cause widespread test flakiness if selector
semantics or WebView switching behavior differs.
> 
> **Overview**
> Migrates MM-Connect performance test coverage off the legacy
`wdio/screen-objects` page objects into new TypeScript page objects
under `tests/page-objects/MMConnect`, built on the unified
`EncapsulatedElement` + `UnifiedGestures` APIs.
> 
> Refactors Playwright/WebdriverIO test utilities by extracting
`boxedStep`/`getDriver` into `PlaywrightUtilities`, expanding
`PlaywrightElement.isVisible`/`waitForDisplayed` to accept WebdriverIO
`isDisplayed` options, and adding a custom `expect.toBeVisible` matcher
in the performance fixture.
> 
> Adds `PlaywrightContextHelpers` to make WebView context switching more
robust (URL matching with a LavaMoat-scuttling fallback) and introduces
shared `MMConnectDappTestIds` plus updated Snap footer selector IDs;
`@wdio/protocols` is added to support typed context APIs.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
804fc1e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Add PredictBuyWithAnyToken view, components, and hooks for the
pay-with-any-token order flow. Includes PredictController, payment token
selection, fee summary, order tracking, navigation, active order
management, feature flag selectors, and full test coverage.

<!--
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 the "Buy With Any Token" flow to prediction markets, enabling users
to place bets using any token in their wallet (not just their predict
balance). When a user doesn't have sufficient USDC.e balance on Polygon,
this flow handles the deposit + order as a single transaction batch
through the confirmations framework.

This is **PR 1 of 2** — contains only `@MetaMask/predict`-owned code. A
follow-up PR will add the confirmations integration (registering the new
`predictDepositAndOrder` transaction type, pay-with-modal changes, and
navigation support).

### What's included

**New view — `PredictBuyWithAnyToken`**
Full buy preview screen with amount input, fee summary, action button,
and payment token selection. Renders both standalone (predict routes)
and within confirmations (as info-root content).

**PredictController state extensions**

- `activeOrder` — tracks order lifecycle (preview → confirming →
success/error)
- `selectedPaymentToken` — stores the user's chosen payment token

**New hooks (13)**
| Hook | Purpose |
|------|---------|
| `usePredictActiveOrder` | Manages active order state in controller |
| `usePredictNavigation` | Navigation helpers with replace support |
| `usePredictPayWithAnyToken` | Triggers deposit+order confirmation flow
|
| `usePredictPaymentToken` | Handles payment token selection changes |
| `usePredictBalanceTokenFilter` | Filters available tokens for predict
context |
| `usePredictBuyPreviewActions` | Orchestrates confirm/back/error
handlers |
| `usePredictBuyConditions` | Derives UI state (canPlaceBet,
isBelowMinimum) |
| `usePredictBuyInfo` | Computes fees, total, toWin from preview |
| `usePredictBuyInputState` | Manages amount input + focus state |
| `usePredictBuyAvailableBalance` | Calculates available balance |
| `usePredictBuyBackSwipe` | Back gesture handler |
| `usePredictOrderTracking` | Tracks order result (success/error) |
| `usePredictPayWithAnyTokenTracking` | Tracks deposit confirmation
lifecycle |

**New components (8)**: PredictBuyActionButton, PredictBuyAmountSection,
PredictBuyBottomContent, PredictBuyMinimumError,
PredictBuyPreviewHeader, PredictFeeSummary, PredictPayWithRow,
PredictPayWithAnyTokenInfo

**Feature flag selectors**: `selectPredictFakOrdersEnabledFlag`,
`selectPredictWithAnyTokenEnabledFlag` — gated behind remote
`predictWithAnyToken` flag.

**Other changes**:

- Routes updated with new navigation stack entries
- Analytics helpers for parsing order event properties
- Transaction constants (chain ID, placeholder address, minimum bet)

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

<!-- [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]
> **High Risk**
> Adds a new deposit+order transaction-batching path
(`payWithAnyTokenConfirmation`) and new controller state for active
orders/payment-token selection, which affects confirmation routing and
transaction submission. Although gated by a remote flag, mistakes could
break Predict order placement/deposit flows or create incorrect
confirmation behavior.
> 
> **Overview**
> Introduces a new *Buy With Any Token* Predict buy-preview flow, gated
by the remote `predictWithAnyToken` flag, and wires Predict routing to
swap `BUY_PREVIEW` between the legacy screen and the new
`PredictBuyWithAnyToken` view.
> 
> Extends `PredictController` with ephemeral `activeOrder` and
`selectedPaymentToken` state plus setters, and adds
`payWithAnyTokenConfirmation()` to submit a deposit transaction batch
that re-tags `predictDeposit` txs as `predictDepositAndOrder` to drive a
new confirmation/info experience.
> 
> Adds supporting hooks/utilities for navigation
(`usePredictNavigation`), active order and token selection
(`usePredictActiveOrder`, `usePredictPaymentToken`,
`usePredictBalanceTokenFilter`), order preview initialization
(`initialPreview`), and shared error/toast + analytics helpers; updates
buy UI components to reflect the new fee summary/deposit-fee row and
improved deposit-in-progress handling. Test coverage is expanded broadly
across the new hooks, selectors, navigation, and controller behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7f6706f. 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**
In the current workflow, the OTA PR needs to point to a base that is the
same as the branch that we are applying the OTA to. However, this does
not work because when we have a release branch, since the base is always
`stable` so we will need to change the base branch whenever we run OTA
update.

In this PR:
- Get rid of hash commit input. We don't really need it because we will
remove the approval if a new commit is pushed and we will always use the
latest commit
- We get the latest commit hash in the OTA PR and output it in the
workflow
- Remove the restriction on the OTA base branch. In the OTA PR, it
shouldn't matter which base branch it's pointing to. We will compare the
fingerprint to the actual release tag that the OTA is applying (which is
one of the inputs when triggering the workflow)

workflow run:
https://github.com/MetaMask/metamask-mobile/actions/runs/23026234415

## **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: Removed OTA workflow commit hash input

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because it changes the OTA release workflow’s
source-of-truth for what gets built/published and removes prior
base-branch/commit validation, which could result in publishing an
unintended revision if PR context is wrong.
> 
> **Overview**
> Updates the OTA `push-eas-update` workflow to publish from a PR’s
**current HEAD commit** rather than a user-supplied commit SHA.
> 
> Reworks `.github/scripts/validate-pr-commit.sh` to *resolve* and
output `commit_sha` for a given `PR_NUMBER` (no longer validates
`COMMIT_HASH` or `BASE_BRANCH`), and wires this new output through
checkout, dependency setup, fingerprint comparison, and the final push
step; the manual `commit_hash` input and the old “validate PR contains
commit” job are removed.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2d9dcd1. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…n rows (TMCU-569) (#27449)

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

## **Description**

This PR adds a dot separator (•) between the price and variation text in
token rows on the homepage, aligning with the `price • variation` format
used in `TokenListItemV2`.

**1. What is the reason for the change?**
- Token rows in the Cash section and Popular Tokens section did not
follow the same layout as token list items
- `TokenListItemV2` displays price and variation as `$1.00 • +5.25%` (or
similar)
- The MUSD row in Cash and the Popular Token rows were missing this
separator

**2. What is the improvement/solution?**
- Insert the Unicode bullet (`\u2022`) between the price and variation
- Update `PopularTokenRow` so price and percentage display as `price •
variation`
- Update `CashGetMusdEmptyState` for the MUSD empty state
- Adjust test assertions in `PopularTokenRow.test.tsx` to match the new
format

## **Changelog**

CHANGELOG entry: Fixed token row display on homepage to show price and
variation separated by a dot for consistency with token list items

## **Related issues**

Fixes:
[TMCU-569](https://consensyssoftware.atlassian.net/browse/TMCU-569)

## **Manual testing steps**

```gherkin
Feature: Homepage token row display consistency

  Scenario: user views token rows with price and variation
    Given the user is on the Homepage
    And the Cash section shows MUSD or Popular Tokens shows tokens with price/variation
    When the user views the token row
    Then price and variation are separated by a dot (•)
    And the layout matches TokenListItemV2 (e.g. "$1.00 • 3% bonus" or "$1,234.56 • +5.25%")
```

## **Screenshots/Recordings**

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

### **Before**

<img width="300"
src="https://github.com/user-attachments/assets/b81022c5-6d85-4f86-9b74-f246503b8475"
/>


### **After**

<img width="300"
src="https://github.com/user-attachments/assets/03c27fe4-07d0-49fa-947f-3fa1ca12efaa"
/>


## **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-only change to text/layout formatting plus corresponding
test updates; no data, auth, or navigation logic changes.
> 
> **Overview**
> Aligns homepage token rows with the `price • variation` display by
inserting a Unicode bullet separator between the price and
percentage/bonus text.
> 
> Updates `PopularTokenRow` to render the separator *only when* a
percentage value is present (and simplifies the layout), and tweaks
`CashGetMusdEmptyState` to show the same separator for the mUSD row.
Tests are updated to assert the new formatting and ensure no trailing
bullet appears when variation is absent/invalid.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
dcda7cd. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
… with Tailwind CSS (#26737)

## **Description**

Replace StyleSheet.create() and useStyles() with useTailwind() and
Box/twClassName in the OnboardingSuccess settings sub-screens:
DefaultSettings, OnboardingAssetsSettings, OnboardingGeneralSettings,
and OnboardingSecuritySettings. Delete the now-unused .styles.ts files.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Refs: [TO-558 - Migrate OnboardingSuccess/DefaultSettings to Design
System (Box/Text +
Tailwind)](https://consensyssoftware.atlassian.net/browse/TO-558)
Refs: [TO-559 - Migrate OnboardingSuccess/OnboardingAssetsSettings to
Design System (Box/Text +
Tailwind)](https://consensyssoftware.atlassian.net/browse/TO-559)
Refs: [TO-560 - Migrate OnboardingSuccess/OnboardingGeneralSettings to
Design System (Box/Text +
Tailwind)](https://consensyssoftware.atlassian.net/browse/TO-560)
Refs: [TO-561 - Migrate OnboardingSuccess/OnboardingSecuritySettings to
Design System (Box/Text +
Tailwind)](https://consensyssoftware.atlassian.net/browse/TO-561)

## **Manual testing steps**

No functional changes. Visual regression only — verify onboarding
settings screens render correctly.

```gherkin
Feature: Onboarding success settings styling

  Scenario: user navigates through default settings
    Given user has completed wallet creation

    When user taps through DefaultSettings, GeneralSettings, AssetsSettings, SecuritySettings
    Then all settings screens render identically to before
```

## **Screenshots/Recordings**

### **Before left, After right**

<img width="500" height="1052" alt="Screenshot 2026-03-02 at 11 22
05 AM"
src="https://github.com/user-attachments/assets/cac80a22-357f-4b61-8a48-3b554e107088"
/>
<img width="500" height="1052" alt="Screenshot 2026-03-02 at 11 22
14 AM"
src="https://github.com/user-attachments/assets/8e207cfb-b6b6-46df-a74d-0eb78d2e0eaa"
/>
<img width="500" height="1052" alt="Screenshot 2026-03-02 at 11 22
21 AM"
src="https://github.com/user-attachments/assets/af0b44a4-e2b5-4b4d-9880-b46893845a09"
/>
<img width="500" height="1097" alt="Screenshot 2026-03-02 at 11 22
32 AM"
src="https://github.com/user-attachments/assets/e5076dc4-cfdc-4326-a9c1-ff09be60ec12"
/>
## **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**
> Primarily a styling refactor (StyleSheet/useStyles -> Tailwind +
design-system `Box`/`Text`) with no intended logic changes; main risk is
minor visual/layout regressions on the onboarding settings screens.
> 
> **Overview**
> **Migrates the OnboardingSuccess settings sub-screens to the new
design system styling approach.** `DefaultSettings`,
`OnboardingAssetsSettings`, `OnboardingGeneralSettings`, and
`OnboardingSecuritySettings` now use `useTailwind()` styles (and
`Box`/design-system `Text` where applicable) instead of
`StyleSheet.create()` + `useStyles()`.
> 
> Removes the now-unused local `*.styles.ts` files and updates Jest
snapshots to reflect the new computed style objects (e.g., flex/padding
and text style differences).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c0ea7f9. 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 the Referral Rewards view, Rewards Settings view, and End of
Season Claim bottom sheet to use the shared `HeaderCompactStandard`
component and consistent safe-area handling, aligning with patterns used
elsewhere in Rewards (e.g. Rewards Dashboard).

1. **Reason for the change:** Referral view used
`getNavigationOptionsTitle` and stack header; Settings and End of Season
Claim used different header primitives (`BottomSheetHeader` in the claim
sheet). This was inconsistent and made safe-area behavior harder to
reason about.
2. **Improvement:** Referral view now uses inline
`HeaderCompactStandard` with `SafeAreaView` and `headerShown: false` for
its stack screen. Settings view SafeAreaView uses `edges={{ top:
'additive' }}` and `HeaderCompactStandard` no longer uses
`includesTopInset`. End of Season Claim bottom sheet uses
`HeaderCompactStandard` instead of `BottomSheetHeader`, with the sheet
title passed as the header `title` prop (custom header title render
removed).

## **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/issues?jql=issueKey%20in%20(DSYS-555%2CDSYS-556)&selectedIssue=DSYS-556

## **Manual testing steps**

```gherkin
Feature: Rewards headers and safe area

  Scenario: Referral Rewards view shows inline header
    Given the app is open and user has access to Rewards

    When user navigates to Referral Rewards
    Then the screen shows HeaderCompactStandard with "Referral" title and back button
    And content is wrapped in SafeAreaView and scrolls correctly

  Scenario: Rewards Settings view header and safe area
    When user navigates to Rewards Settings
    Then the header and content respect safe areas (top additive)
    And the back button and title display correctly

  Scenario: End of Season Claim bottom sheet header
    When user opens the End of Season Claim bottom sheet (when applicable)
    Then the sheet shows HeaderCompactStandard with the reward title and close button
    And the sheet content and keyboard behavior are unchanged
```

## **Screenshots/Recordings**

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

### **Before**

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

### **After**
<img width="1290" height="2796" alt="Simulator Screenshot - iPhone 15
Pro Max - 2026-03-10 at 16 32 06"
src="https://github.com/user-attachments/assets/ec4e8d4a-044e-4752-8a66-26c6d3b06b8b"
/>

<img width="1290" height="2796" alt="Simulator Screenshot - iPhone 15
Pro Max - 2026-03-10 at 16 35 28"
src="https://github.com/user-attachments/assets/3d84c6af-0f6f-477c-b648-86651ebd692b"
/>

<img width="1290" height="2796" alt="Simulator Screenshot - iPhone 15
Pro Max - 2026-03-10 at 16 42 41"
src="https://github.com/user-attachments/assets/2d0c0294-3696-4016-a6c2-63411fa24200"
/>


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

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UI refactor affecting header rendering and safe-area insets
on a few Rewards screens; main regression risk is incorrect insets or
back/close behavior.
> 
> **Overview**
> Unifies Rewards header behavior by moving the Referral screen off the
stack header (`headerShown: false`) and rendering an inline
`HeaderCompactStandard` inside a `SafeAreaView`.
> 
> Adjusts Rewards Settings safe-area handling to use `edges={{ top:
'additive' }}` (and removes `includesTopInset` from the header) for more
consistent inset behavior.
> 
> Replaces the End-of-Season claim sheet’s `BottomSheetHeader` with
`HeaderCompactStandard`, using the reward `title` directly (and removing
the previous non-LINEA custom title renderer), and updates/streamlines
associated tests accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1affda9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

Migrate Skeleton to use DSRN.

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

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


https://github.com/user-attachments/assets/045473e8-541f-4e7f-ad34-03527a59e92b

### **After**


https://github.com/user-attachments/assets/179f2212-5fe8-415b-954f-c19243c79627

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Mostly mechanical import/mocking changes to swap Rewards screens and
tests over to the new `components-temp` `Skeleton`; functional risk is
limited to loading placeholders rendering/autoPlay behavior.
> 
> **Overview**
> Migrates the Rewards UI (onboarding, season status, previous season,
referral details, settings, and tabs) to use the new
design-system-backed `Skeleton` from
`component-library/components-temp/Skeleton` instead of the legacy
component.
> 
> Updates associated unit tests to mock the new `Skeleton` module paths
and types so loading-state coverage continues to pass.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b310d00. 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**

migrate renderBottomContent into independent component

<!--
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: N/A

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/SWAPS-4101

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] 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 refactor that moves existing footer rendering logic into a
new component and adds targeted tests; main risk is minor UI regression
in when the confirm button/banners/disclaimer render.
> 
> **Overview**
> Extracts `BridgeView`’s inline `renderBottomContent` into a new
`BridgeViewFooter` component and wires it into `BridgeView`, removing
the duplicated footer logic and related imports.
> 
> Adds a dedicated `BridgeViewFooter.test.tsx` covering render gating
(loading/no quote/missing amount), hardware-wallet Solana banner,
Blockaid alert banner, fee/no-fee disclaimer, and approval
disclaimer/tooltip, while deleting the corresponding footer-specific
tests from `BridgeView.test.tsx`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
8721336. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…27416)

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

Allow user to send to contract address, but add warning for that on both
send and confirmation page.

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes: MetaMask/MetaMask-planning#6962

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


https://github.com/user-attachments/assets/3cd4e562-5f4f-40fd-a498-805a495d7d19

## **Pre-merge author checklist**

- [X] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [X] I've completed the PR template to the best of my ability
- [X] I've included tests if applicable
- [X] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [X] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes recipient validation and submission gating so some address
errors become acknowledgeable, which can affect when transactions are
allowed to proceed. Also adds a new confirmation alert source and
metrics mapping; incorrect classification could lead to missed warnings
or unintended sends.
> 
> **Overview**
> Users can now proceed when the recipient is detected as a
token/smart-contract address by acknowledging a new `SendAlertModal`,
instead of being hard-blocked at the recipient step.
> 
> This introduces an *acknowledgeable* validation state
(`toAddressErrorAllowAcknowledge`) from
`useToAddressValidation`/`validateHexAddress`, adds a new
confirmation-page warning via `useTokenContractAlert`
(`AlertKeys.TokenContractAddress`), and wires the new alert key into
confirmation alert metrics/name resolution. Tests and i18n strings were
updated/added to cover the modal flow and the new alert behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fa22e95. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…26353)

<!--
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**
Removes legacy cancel/speed-up code and consolidates on the single
`CancelSpeedupModal` flow. This includes dropping unused EIP-1559 modal
state and deleting legacy confirmation components that are no longer
used.

## Motivation

- The cancel/speed-up flow now uses only `CancelSpeedupModal` (with
`useCancelSpeedupGas`). The previous EIP-1559–specific modal state
(`speedUp1559IsOpen`, `cancel1559IsOpen`) was never set to `true` and
only reset to `false`, so it was dead code.
- Legacy confirmation components (`EditGasFee1559Update`,
`EditGasFeeLegacyUpdate`, `UpdateEIP1559Tx`) have been superseded by the
unified cancel/speed-up flow and are no longer referenced.

## Changes

### Legacy state cleanup

- **`useUnifiedTxActions`**: Removed `speedUp1559IsOpen` and
`cancel1559IsOpen` state, their setters in open/close/error paths, and
from the hook’s return value. Only `speedUpIsOpen` and `cancelIsOpen`
are used with `CancelSpeedupModal`.
- **`Transactions/index.js`**: Removed `speedUp1559IsOpen` and
`cancel1559IsOpen` from component state and from all `setState` calls in
`onSpeedUpCompleted`, `onCancelCompleted`, and the speed-up/cancel
failure handlers.
- **Tests**: Updated `useUnifiedTxActions.test.ts`,
`UnifiedTransactionsView.test.tsx`, and `Transactions/index.test.tsx` to
drop assertions and mocks for the removed 1559 modal state.

### Legacy component removal

- **Deleted**
`app/components/Views/confirmations/legacy/components/EditGasFee1559Update/`
(index, styles, types).
- **Deleted**
`app/components/Views/confirmations/legacy/components/EditGasFeeLegacyUpdate/`
(component, styles, types, test, snapshot).
- **Deleted**
`app/components/Views/confirmations/legacy/components/UpdateEIP1559Tx/`
(index, types).

Cancel/speed-up is now handled solely by `CancelSpeedupModal` in both
`UnifiedTransactionsView` and the legacy `Transactions` list.

Manual: open Activity, trigger Speed up or Cancel on a pending
transaction and confirm the modal and flow behave as before.

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes: MetaMask/mobile-planning#2411

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


[test speed
up.webm](https://github.com/user-attachments/assets/446714f1-5a00-4610-bfda-7daa8d935c12)



[test-cancel.webm](https://github.com/user-attachments/assets/12b1e62a-cc56-4f15-997c-eadee620f771)

<!-- 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**
> Touches the speed-up/cancel transaction flow by removing legacy
UI/components and slightly refactoring param handling; regressions would
affect replacing pending transactions if any removed paths were still
reachable.
> 
> **Overview**
> Removes the deprecated legacy gas-edit components and snapshots for
speed-up/cancel flows (including `EditGasFee1559`, `EditGasFeeLegacy`,
`EditGasFee*Update`, and `UpdateEIP1559Tx`), consolidating on the single
`CancelSpeedupModal`-based path.
> 
> Cleans up related code and tests by dropping now-unused mocks/state
and minor refactoring in `useUnifiedTxActions` to compute gas params
once before dispatching speed-up/cancel actions. Also fixes formatting
in `docs/readme/deeplinking.md` by converting an admonition block into
plain blockquoted lines.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c46bdd8. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…SS (Part 1) (#26673)

## **Description**

Replace StyleSheet.create() and raw View/Text components with
design-system-react-native Box/Text and useTailwind() in Onboarding,
OnboardingSheet, OnboardingSuccess, and OnboardingSuccessEndAnimation.
Delete the now-unused .styles.ts files.

Part 1 of 2. Part 2 will cover ImportFromSecretRecoveryPhrase and
ImportNewSecretRecoveryPhrase.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Refs: [TO-555 - Migrate Onboarding screen to Design System (Box/Text +
Tailwind)](https://consensyssoftware.atlassian.net/browse/TO-555)
Refs: [TO-556 - Migrate OnboardingSuccess screen to Design System
(Box/Text +
Tailwind)](https://consensyssoftware.atlassian.net/browse/TO-556)
Refs: [TO-557 - Migrate OnboardingSuccessEndAnimation to Design System
(Box/Text +
Tailwind)](https://consensyssoftware.atlassian.net/browse/TO-557)

## **Manual testing steps**

No functional changes. Visual regression only — verify onboarding
screens render correctly.

```gherkin
Feature: Onboarding screens styling

  Scenario: user views onboarding screens
    Given app is freshly installed

    When user launches the app and reaches onboarding
    Then all onboarding screens render identically to before
```

## **Screenshots/Recordings**

Before (left) vs After (right)


<img width="500" height="1053" alt="Screenshot 2026-03-04 at 7 02 57 PM"
src="https://github.com/user-attachments/assets/9da681a1-75c9-428e-b0d7-830d43bb6797"
/>

<img width="500" height="1041" alt="Screenshot 2026-03-04 at 7 06 40 PM"
src="https://github.com/user-attachments/assets/7c74f068-0fb2-4d75-bde9-e731229703c8"
/>

<img width="500" height="1007" alt="Screenshot 2026-03-04 at 7 40 13 PM"
src="https://github.com/user-attachments/assets/ff427500-8f99-459d-8a24-7ab9b5becd4b"
/>


## **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]
> **Medium Risk**
> Mostly a UI refactor, but it touches the onboarding entry flow (CTA
buttons, loading overlay, and success notification padding/animation),
so layout/interaction regressions are possible across device sizes.
> 
> **Overview**
> Migrates `Onboarding`, `OnboardingSheet`, and
`OnboardingSuccessEndAnimation` from `StyleSheet`/raw `View`/custom
component-library buttons to `@metamask/design-system-react-native`
(`Box`, `Button`, `Text`, `TextButton`) styled via `useTailwind()`, and
deletes the now-unused styles files.
> 
> Updates onboarding UI behavior/styling to be device-aware in Tailwind
(medium-device CTA spacing/button size, iPhoneX vs non-iPhoneX
notification padding) and adds a cleanup for the notification hide timer
on unmount.
> 
> Expands unit tests and snapshots to cover the new responsive styling,
the loading overlay message, iPhoneX notification padding variants, and
safe handling when `OnboardingSheet` route params are `undefined`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
792bfdf. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
#26783)

## **Description**

On iOS, the Ledger connect illustration was cut off when opening the
Ledger flow after the keyboard had been shown (e.g. search in Explore,
then back). Removed `overflow: 'visible'` from the cover image style so
the layout no longer gets clipped. Also fixed a typo in
LedgerSelectAccount: `style-=` → `style=` so the selector container gets
its styles.

## **Changelog**

CHANGELOG entry: Fixed Ledger connect screen image being cut off on iOS
after using the keyboard.

## **Related issues**

Fixes: #25760

## **Manual testing steps**

Feature: Ledger connect screen

  Scenario: user opens Ledger connect after using keyboard
Given the app is open and user has been to Explore and opened the search
keyboard then navigated back

    When user starts connecting a Ledger device
    Then the Ledger connect illustration is fully visible (not cut off)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk, UI-only style tweaks plus a snapshot update; potential
impact is limited to Ledger connect/select-account screen layout across
devices.
> 
> **Overview**
> Prevents the Ledger connect illustration from being clipped (notably
on iOS after keyboard interactions) by removing `overflow: 'visible'`
from the `LedgerConnect` cover image styling, and updates the Jest
snapshot accordingly.
> 
> Adjusts `LedgerSelectAccount` layout by removing `flex: 1` from
`selectorContainer` to ensure the selector section sizes/positions
correctly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d6b0203. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
…7478)

<!--
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 GitHub Actions workflow to accept an optional dispatch input
and pass it through with a safe default

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

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: only updates a GitHub Actions workflow to accept an optional
dispatch input and pass it through with a safe default, without touching
application code.
> 
> **Overview**
> Adds a `workflow_dispatch` input (`lookback-days`, default `1`) to the
Post Merge Validation GitHub Actions workflow.
> 
> Passes this value through to the `MetaMask/github-tools`
`post-merge-validation@v1` action (falling back to `1` when not
provided) to control how far back the workflow searches for PRs.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a214512. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ests (#27473)

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

## **Description**


**Reason for change:** In the Cash section (homepage), the "Claim bonus"
CTA was shown even when the claimable mUSD bonus was less than $0.01
(e.g. dust after claiming). Small amounts like 0.007401 were also
displayed as "0.01" because the formatting logic rounded to 2 decimals
instead of showing "< 0.01".

**Improvement / solution:**

1. **MusdAggregatedRow (Cash section):** Only show the "Claim bonus"
button when the claimable reward is at least $0.01. Introduced
`MIN_CLAIMABLE_BONUS_USD` and `isClaimableBonusAboveThreshold(reward)`;
below that threshold the row shows the static "3% bonus" text instead of
the CTA.

2. **useMerklRewards:** Removed use of `renderFromTokenMinimalUnit`,
which only treated values below 0.00001 as "< 0.00001" and rounded
everything else (e.g. 0.007401 → "0.01"). The hook now computes the
decimal value as `unclaimedBaseUnits / 10^tokenDecimals` and formats it
as `"< 0.01"` when &lt; 0.01, otherwise `toFixed(2)`. This ensures
amounts like 0.007401 display as "< 0.01" and the Cash section threshold
logic works correctly.

3. **Tests:** MusdAggregatedRow tests for the claimable-bonus threshold
(hide CTA for "< 0.01", "0.01", "0.005"; show for "0.02").
useMerklRewards tests updated to assert outcomes instead of mocking
`renderFromTokenMinimalUnit`; added case for 7401 with 6 decimals → "<
0.01".

## **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 Cash section showing "Claim bonus" for amounts
under $0.01 and corrected display of small claimable amounts as "< 0.01"

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MUSD-513

## **Manual testing steps**

```gherkin
Feature: Cash section claim bonus threshold and small-amount display

  Scenario: Claim bonus CTA hidden when claimable amount is below $0.01
    Given I am on the Wallet home screen with the Cash section visible
    And my claimable mUSD bonus is less than $0.01 (e.g. dust after claiming)

    When I view the mUSD row in the Cash section
    Then I should see "3% bonus" (green text) instead of "Claim bonus"
    And I should not see a tappable "Claim bonus" link

  Scenario: Claim bonus CTA shown when claimable amount is at least $0.01
    Given I am on the Wallet home screen with the Cash section visible
    And my claimable mUSD bonus is at least $0.01

    When I view the mUSD row in the Cash section
    Then I should see the "Claim bonus" link
    And tapping it should start the claim flow
```

## **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/ec20c986-1694-4f45-9e8b-4bb9eaed36d0


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

### **After**
<img width="391" height="845" alt="Screenshot 2026-03-16 at 09 07 21"
src="https://github.com/user-attachments/assets/797d36f7-bf62-47e6-a544-299becef83b0"
/>

<!-- [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**
> Changes reward amount formatting and CTA gating logic in the Cash
section; incorrect numeric conversion/rounding (notably
`BigInt`→`Number`) could mis-display large rewards or edge-case
decimals.
> 
> **Overview**
> **Fixes dust claim UX in the Cash section.** `MusdAggregatedRow` now
only shows the **"Claim bonus"** CTA when the claimable bonus is at
least `$0.01`; otherwise it shows the static **"3% bonus"** label
(including when the hook returns `"< 0.01"`).
> 
> **Simplifies Merkl claimable reward formatting.** `useMerklRewards`
drops `renderFromTokenMinimalUnit` and instead computes the decimal
amount directly from base units, returning `"< 0.01"` for anything below
`$0.01` and `toFixed(2)` otherwise.
> 
> **Tests updated/added.** Merkl reward tests no longer mock the
formatter and add coverage for sub-$0.01 amounts (including cases that
previously rounded up), and Cash row tests cover the new $0.01 CTA
threshold behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1054f6f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
… view support and update event tracking locations (#27415)

<!--
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 `mUSD Conversion CTA Clicked` event in `CashGetMusdEmptyState`
always sent `location: 'home_cash_section'`, even when the CTA was
tapped from the full Cash token list page.

This PR adds a new `MOBILE_TOKEN_LIST_PAGE` event location and an
`isFullView` prop to `CashGetMusdEmptyState` so the full-page context is
reported correctly, while the homepage default (`home_cash_section`)
remains unchanged:

- **`CashGetMusdEmptyState`** — accepts `isFullView`; sends
`mobile-token-list-page` when true, keeps `home_cash_section` otherwise.
- **`CashTokensFullView`** — passes `isFullView` to
`CashGetMusdEmptyState`.

## **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/TMCU-560

## **Manual testing steps**

```gherkin
Feature: mUSD Conversion CTA location tracking in Cash section

  Scenario: CTA clicked on homepage Cash section keeps home_cash_section location
    Given the user is on the wallet homepage with mUSD conversion enabled
    And the user has no mUSD balance (Cash empty state is shown)

    When user taps the "Get mUSD" button in the Cash section
    Then the mUSD Conversion CTA Clicked event fires with location "home_cash_section"

  Scenario: CTA clicked on full Cash token list page sends mobile-token-list-page location
    Given the user navigates to the full Cash token list page (via ">" from homepage Cash section)
    And the user has no mUSD balance (Cash empty state is shown)

    When user taps the "Get mUSD" button
    Then the mUSD Conversion CTA Clicked event fires with location "mobile-token-list-page"
```

## **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]
> **Low Risk**
> Low risk: limited to analytics metadata and a new optional prop wiring
for `CashGetMusdEmptyState`, with updated unit coverage.
> 
> **Overview**
> Updates mUSD conversion CTA analytics so the
`MUSD_CONVERSION_CTA_CLICKED` event reports the correct `location` when
triggered from the full Cash token list page.
> 
> Adds `EVENT_LOCATIONS.MOBILE_TOKEN_LIST_PAGE` and an `isFullView` prop
to `CashGetMusdEmptyState`, passes it from `CashTokensFullView`, and
extends tests to cover both homepage (`home_cash_section`) and full-view
tracking.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
720ef20. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…27475)

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

Removes background on the "+" icon in the new Network management view.

## **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: Remove background from Additional Networks in Network
Management

## **Related issues**

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

## **Manual testing steps**

```gherkin
Feature: Network management

  Scenario: user can access network management and sees updated additional network icons
    Given the app is opened and the user is logged in
    When the user goes to Account Menu and opens Networks
    Then the Networks management screen is shown
    And each additional network item shows its icon without a rounded muted background
```

## **Screenshots/Recordings**

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

### **Before**
<img width="384" height="833" alt="Screenshot 2026-03-16 at 11 27 32"
src="https://github.com/user-attachments/assets/cfb05217-da81-4434-9d42-31c4f5fc395a"
/>

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

### **After**
<img width="388" height="837" alt="Screenshot 2026-03-16 at 11 27 41"
src="https://github.com/user-attachments/assets/7818cb86-088c-4cb4-af68-a2eb7302192c"
/>

<!-- [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 UI-only change that adjusts styling for the add (+) button
with no logic or data flow changes.
> 
> **Overview**
> Updates `AdditionalNetworkItem` so the add (+) `Pressable` no longer
renders with a muted rounded background, leaving only sizing/alignment
and pressed opacity styling.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c27272c. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

We have a few areas in the app that perform fetch requests outside of
the engine, by using `core` services. Some examples:
- Perps
- Predict
- Explore

This PR adds the `nock` mock API requests library that we use for unit
tests in `MetaMask/core` and `MetaMask/metamask-extension`.
- It allows us to strictly mock API calls and not the whole core
service, for more realistic integration tests.

## **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: test: CV - add `nock` and cleanup Trending CV services
mocks

## **Related issues**

Fixes: #26270
https://consensyssoftware.atlassian.net/browse/ASSETS-2734

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] 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**
> Test-only changes that swap service-function mocking for HTTP
interception; risk is limited to potential flakiness/over-blocking of
network calls in view tests if nock isn’t cleaned up correctly.
> 
> **Overview**
> Switches Trending component-view tests from mocking
`@metamask/assets-controllers` (`getTrendingTokens`) to mocking the
actual trending HTTP endpoint via **`nock`**, making the tests exercise
the real fetch path.
> 
> Updates `tests/component-view/mocks/trendingApiMocks.ts` to define
nock-based helpers (including optional per-request reply logic for chain
filtering), adds `nock` to `devDependencies`, and simplifies the
Trending view tests accordingly (removing `itForPlatforms`/controller
mocks and using request-URL-based responses for the BNB filter case).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fc3106d. 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.71.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.71.0
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

NFT images in the grid had no loading indicator — the cell would appear
empty until the image finished loading. This PR adds a skeleton overlay
that shows immediately when an NFT item has an image URL, then
disappears once the image loads or fails.

**Changes:**
- `NftGridItem`: Tracks a local `isImageLoading` state (true when
`item.image` or `item.imageOriginal` is set). Renders a `Skeleton`
overlay on the image cell until `onLoad` fires. Resets correctly when
the item changes.
- `CollectibleMedia` + `CollectibleMedia.types`: Adds an `onLoad` prop
wired through to `RemoteImage`. Also calls it in the error fallback so
the skeleton always clears even when an image fails to load.
- `RemoteImage`: Adds an `onLoad` prop called from the internal
`onImageLoad` handler. Adds `recyclingKey={uri}` to expo-image `Image`
components so cached images are reused correctly when URIs change.
- `NftGrid`: Improves `keyExtractor` from an array-index key to a stable
`${chainId}-${address}-${tokenId}` key, preventing unnecessary
re-renders when the list updates.

## **Changelog**

CHANGELOG entry: Added skeleton loading indicator to NFT grid items
while images are loading

## **Related issues**

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

## **Manual testing steps**

```gherkin
Feature: NFT grid skeleton loading

  Scenario: user views the NFT grid while images load
    Given the user has NFTs in their wallet
    When the user navigates to the NFT grid
    Then a skeleton placeholder is visible on each NFT cell while the image loads
    And the skeleton disappears once the image finishes loading

  Scenario: user views an NFT whose image fails to load
    Given the user has an NFT with an unreachable image URL
    When the NFT grid renders that item
    Then the skeleton disappears even though no image is shown
```

## **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/00107c9f-5d61-4a2c-89fb-5e46bf442756


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

### **After**


https://github.com/user-attachments/assets/9d690211-1ebd-40a8-b7a8-4b8782bbeb93


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

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches NFT grid rendering by adding loading state/skeleton overlays
and changing list keys, which can affect perceived UI behavior and item
reuse. Also propagates new `onLoad` callbacks through image components,
so regressions would mainly be around image lifecycle events and
re-rendering.
> 
> **Overview**
> Adds a **skeleton loading overlay** to `NftGridItem` that shows when
an NFT has an image (and media display is enabled) and hides when the
underlying media reports `onLoad`.
> 
> Threads a new `onLoad` callback through `CollectibleMedia` →
`RemoteImage`, and ensures the callback also fires on image error
fallback so the skeleton clears even when an image fails. `RemoteImage`
now sets `recyclingKey={uri}` on `expo-image` instances and invokes the
new `onLoad` prop from its internal load handler.
> 
> Updates `NftGrid` to use a stable `keyExtractor`
(`chainId-address-tokenId`) instead of index keys, and adds/updates unit
tests covering the new `onLoad` behavior and skeleton visibility.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e382cc8. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
….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 -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

This PR refines the main action buttons to match the design specs.
Update the vertical padding from `16px` > `12px` to improve the spacing.

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

### **After**

<img width="1442" height="562" alt="Screenshot 2026-03-11 at 7 43 58 PM"
src="https://github.com/user-attachments/assets/9adf2473-7c9d-4d2d-acca-b65df3284398"
/>


## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk visual-only spacing change that updates styles and
corresponding Jest snapshots without altering behavior or data flow.
> 
> **Overview**
> Polishes `MainActionButton` spacing by reducing `paddingVertical` from
`16` to `12` in `MainActionButton.styles.ts` to better match design
specs.
> 
> Updates Jest snapshots for `MainActionButton` and screens that render
it (e.g., `AccountsMenu` scan button and `AssetDetailsActions` buttons)
to reflect the new padding.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0950cef. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
….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 -->
@chloeYue chloeYue requested review from a team as code owners March 27, 2026 08:29
chloeYue
chloeYue previously approved these changes Mar 27, 2026
@chloeYue chloeYue added team-mobile-delivery and removed auto-rc-builds enable automatic release candidate builds labels Mar 27, 2026
…27708) (#28016)

## Description

Merges `stable` into `release/7.71.0` and resolves `CHANGELOG.md`
conflicts so [PR
#27708](#27708)
(`release/7.71.0` → `stable`) can merge cleanly.

### CHANGELOG resolution (per local release changelog guidelines)

- Kept **`## [7.71.0]`** (cleaned release notes) **above** **`##
[7.70.1]`** / **`## [7.70.0]`** from stable.
- **Compare links:** `[Unreleased]` → `v7.71.0...HEAD`; `[7.71.0]` →
`v7.70.1...v7.71.0`; left `[7.70.1]` / `[7.70.0]` lines unchanged below.

### After this PR

1. Merge this PR into `release/7.71.0` using **Create a merge commit**
(not squash), per release process.
2. Re-try / update [PR
#27708](#27708).

## Changelog

CHANGELOG entry: null

---

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: merge-conflict resolution focused on `CHANGELOG.md`
ordering/compare links with no runtime code changes.
> 
> **Overview**
> Merges `stable` into `release/7.71.0` and resolves the `CHANGELOG.md`
conflict by keeping the cleaned `7.71.0` notes above `7.70.1`/`7.70.0`
and updating the compare links (`[Unreleased]` → `v7.71.0...HEAD`,
`[7.71.0]` → `v7.70.1...v7.71.0`).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
424324a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@github-actions
Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

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

All E2E tests pre-selected.

View GitHub Actions results

@sonarqubecloud
Copy link
Copy Markdown

@github-actions
Copy link
Copy Markdown
Contributor

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

@chloeYue chloeYue merged commit da79e69 into stable Mar 27, 2026
205 of 217 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Mar 27, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.71.0 Issue or pull request that will be included in release 7.71.0 size-XL team-mobile-delivery

Projects

None yet

Development

Successfully merging this pull request may close these issues.