Skip to content

[pull] main from MetaMask:main#490

Merged
pull[bot] merged 17 commits into
Reality2byte:mainfrom
MetaMask:main
Jan 30, 2026
Merged

[pull] main from MetaMask:main#490
pull[bot] merged 17 commits into
Reality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Jan 30, 2026

See Commits and Changes for more details.


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

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

michalconsensys and others added 17 commits January 30, 2026 08:31
…#25412)

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

Refactor perps controller and remove unused route

## **Changelog**

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] -->
No visible change

### **After**

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

No visible change

## **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**
> Medium risk because it changes the public
`PerpsController.depositWithConfirmation`/hook call signatures and the
deposit+order transaction path toggle, which could break existing
callers if any weren’t updated.
> 
> **Overview**
> **Refactors perps deposit entrypoints** by changing
`PerpsController.depositWithConfirmation` from positional args to a
single `DepositWithConfirmationParams` object (`amount`, `placeOrder`),
and updates `depositWithOrder`/`usePerpsTrading` accordingly.
> 
> **Cleans up navigation** by removing the unused `Routes.PERPS.ORDER`
constant and its screen registration from the perps route stack. Tests
are updated to match the new deposit API shape.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
8ac4035. 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**
Added comprehensive component view tests for the following mUSD
conversion components:

1. **MusdConversionAssetListCta** (3 test cases)
- Feature flag visibility logic (`earnMusdCtaEnabled` and
`earnMusdConversionFlowEnabled`)
   - Component behavior when visibility conditions are not met
   - Graceful handling when component returns null

2. **MusdConversionAssetOverviewCta** (15 test cases)
- Component rendering with different asset configurations (USDC, DAI,
USDT)
   - CTA text content verification (title and description)
   - Close button visibility and interaction (`onDismiss` callback)
- Presentational component behavior (renders regardless of allowlist -
logic handled by parent)
   - Asset balance scenarios (above minimum, low balance)
   - Multi-chain support (different chainIds)
   - Edge cases (missing asset address, assets not in allowlist)
- Feature flag configuration
(`earnMusdConversionAssetOverviewCtaEnabled`,
`earnMusdConversionFlowEnabled`, `earnMusdConversionCtaTokens`)

3. **EarnMusdConversionEducationView** (12 test cases)
- Complete UI rendering (heading, description, primary and secondary
buttons)
   - APY percentage display in heading and description
- Button interaction states (go back and continue buttons remain visible
after press)
- Route parameter handling (missing params, partial params, complete
params)
   - Education seen state management (`musdConversionEducationSeen`)
   - Feature flag configuration (`earnMusdConversionFlowEnabled`)


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

## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds comprehensive component-view tests for mUSD conversion UI and
strengthens the test harness/mocks for stable execution.
> 
> - New tests cover `EarnMusdConversionEducationView`,
`MusdConversionAssetListCta`, and `MusdConversionAssetOverviewCta`
including feature flag gating, visibility conditions, APY text, route
params handling, and interaction (press/close)
> - Test utilities enhanced: Engine mock gains
`controllerMessenger.call`; state fixture builder adds
`withMinimalAnalyticsController`; wallet/bridge presets include minimal
analytics and `TokensController` defaults; expanded
RN/analytics/filesystem mocks in `testSetupView`
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0a53be7. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ontrollers (#25376)

## **Description**
Bump transaction-pay-controller to ^12.0.2

Release notes:
https://github.com/MetaMask/core/blob/main/packages/transaction-pay-controller/CHANGELOG.md

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

## **Manual testing steps**


## **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**
> Upgrades core transaction/payment-related controller dependencies,
which can affect transaction submission, fees, and bridging behavior
despite no app-code changes.
> 
> **Overview**
> Bumps `@metamask/transaction-pay-controller` from `^11.1.0` to
`^12.0.2`.
> 
> Updates dependency resolution/lockfile to align with newer controller
versions (notably `@metamask/assets-controllers` up to `99.1.0`,
`@metamask/bridge-controller` to `65.1.0`,
`@metamask/bridge-status-controller` to `65.0.1`, and
`@metamask/transaction-controller` to `^62.11.0`), including adding a
`resolutions` entry so the existing `transaction-controller` patch also
applies to `^62.11.0`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
812ad65. 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**

- MusdConversionAssetOverviewCta: Align text assertions with current
i18n (boost_title / boost_description); use MUSD_CONVERSION_APY and drop
redundant getByText('mUSD').

- EarnMusdConversionEducationView: Match description via regex
(description is rendered with " Terms apply." in the same Text); assert
APY percentage on children[0] instead of children.

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

## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: changes are limited to component-view test assertions and
how text is matched/inspected, with no production logic modifications.
> 
> **Overview**
> Updates mUSD conversion component-view tests to match the current
rendered copy and i18n behavior.
> 
> The education view tests now match the description via regex (to
tolerate the appended “Terms apply.” text) and adjust APY assertions to
check the first child node. The asset overview CTA tests switch to
asserting the new `boost_title`/`boost_description` strings using
`MUSD_CONVERSION_APY`, and remove redundant checks for a separate `mUSD`
text node.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
03c42f6. 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.64.0 to 7.65.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.64.0` to `7.65.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.64.0
- Release branch: release/7.64.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>
Co-authored-by: João Loureiro <175489935+joaoloureirop@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**

Replaced URL substring check with hostname comparison for portfolio site
identification to fix a security vulnerability.

This should be pretty safe since we own the underlying data, but still
good practice to use stricter url condition.

## **Changelog**

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

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

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

CHANGELOG entry: fix: strengthen explore portfolio site condition

## **Related issues**

Fixes:
https://github.com/MetaMask/metamask-mobile/security/code-scanning/134

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

---
<a
href="https://cursor.com/background-agent?bcId=bc-6ac797b6-6854-4d64-89f8-a169dec92a38"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/agents?id=bc-6ac797b6-6854-4d64-89f8-a169dec92a38"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: small, localized change to Portfolio site detection logic;
the main risk is accidentally missing/duplicating the Portfolio entry if
URL parsing/normalization behaves unexpectedly for edge-case inputs.
> 
> **Overview**
> Strengthens how the Explore sites list detects whether MetaMask
Portfolio is already present by replacing a
`url.includes('portfolio.metamask.io')` substring check with strict
hostname parsing/comparison.
> 
> Adds `PORTFOLIO_HOSTNAME` and a new `isPortfolioSiteUrl()` normalizer
(handles missing schemes/whitespace) and uses it in `mergePortfolioSite`
to avoid false matches that could let non-Portfolio URLs bypass or
trigger the Portfolio entry logic.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3214479. 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**
After trying to debug an e2e test that was failing on the CI, I
attempted to set up my local environment to run these same e2e tests.

After a lot of trial and error, I managed to get them running, I have
updated the Docs that explain how to get started and improved the
`install-ios-runway-app` script so that it can be reused for this
scenario which simplifies the tester's life and prevents them from
having to download the build manually from runway

<!--
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: simplify local e2e testing setup

## **Related issues**

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

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Changes are limited to developer documentation and a local iOS Runway
install helper script; risk is mainly around breaking existing local
workflows due to the new `build/` artifact location and fixed
`MetaMask.app` naming.
> 
> **Overview**
> Simplifies local E2E setup docs by restructuring the flow into **App
Build** (Expo prebuild download vs local build) and **Run the E2E
Tests** (explicit two-terminal Metro/test execution steps), with clearer
commands for running all tests, a folder, a file, or by tag.
> 
> Updates `install-ios-runway-app.sh` to store Runway artifacts in
`build/`, always extract/expect `MetaMask.app`, and adds `--skipInstall`
to support download-only runs without requiring a booted simulator.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3fcfa65. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…rts (#25326)

- Update pay token selection to use hasTransactionType for predict
deposit detection (covers nested/batch txs), and tighten typing/guarding
around transactionMeta when updating selectedGasFeeToken. Perps behavior
remains unchanged.
- Suppress the native insufficient balance alert when the pay token
matches the required token and pay‑controller quotes are
loading/available, letting pay‑token balance/fee alerts drive blocking
instead.
- Add unit coverage for the quote‑present case and expand mocks for
quote/loading state in useInsufficientBalanceAlert tests.

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

## **Description**

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

## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes blocking alert behavior and updates how `selectedGasFeeToken`
is set during pay-token selection for `predictDeposit`, which could
impact confirmation gating and gas/token selection in edge cases.
> 
> **Overview**
> **Confirmation alerts now defer to transaction-pay UI when pay
quotes/source amounts are in play.** `useInsufficientBalanceAlert` stops
emitting the native insufficient-balance blocking alert whenever
`useTransactionPayHasSourceAmount()` indicates pay source amounts are
being used, replacing the prior pay-token/required-token matching logic.
> 
> **Pay-token selection for `predictDeposit` is more robust.**
`useTransactionPayToken` uses `hasTransactionType` to detect
`predictDeposit` (covering nested/batch transactions) and only updates
`selectedGasFeeToken` when `transactionMeta` is present, with tighter
typing.
> 
> Tests for `useInsufficientBalanceAlert` were updated to mock
`useTransactionPayHasSourceAmount` and cover the new suppression
behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
567382e. 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**
Adds E2E tests for the mUSD conversion happy path, covering the main
user flows and aligning with project E2E guidelines.

### Test scenarios

- **First-time user:** Education screen → custom amount → transaction
confirmation → back to wallet → Activity tab shows confirmed mUSD
conversion.
- **Returning user (Token List):** Direct conversion from token list
item CTA (“Get X% mUSD bonus” on USDC row); education skipped; same
confirmation and Activity verification.
- **Asset Overview:** Tap USDC → Asset Overview → scroll to mUSD CTA →
tap → confirmation → back to wallet → Activity verification.

### Technical improvements

- **Fixture & mocks**
- `createMusdFixture(node, options)` moved to
`e2e/specs/wallet/helpers/musd-fixture.ts` (Mainnet, ETH/USDC/mUSD,
rates, balances, geo/ramp state).
- API mocks (feature flags, geolocation, ramp tokens, price APIs, token
API, Relay quote/status) moved to
`e2e/specs/wallet/helpers/musd-mocks.ts`; feature flag key fixed to
`earnMusdConversionAssetOverviewCtaEnabled` for Asset Overview CTA.
- **Page Object Model**
- **WalletView:** `scrollDownToAssetOverviewMusdCta()` (scroll in Asset
Overview until CTA visible, then assert); `tapAssetOverviewMusdCta()`
with `checkStability` and delay; token list item CTA getter/tap with
stability.
- **TransactionPayConfirmation:** `enterAmountAndContinue(amount)` for
keyboard amount + continue.
- **ActivitiesView:** `verifyMusdConversionConfirmed(rowIndex)` and
generic `verifyActivityItemWithStatus(title, status, rowIndex)`; uses
`ActivitiesView.testIds` for mUSD conversion label.
- **Framework usage**
- Assertions, Gestures, Matchers from `tests/framework`; no direct Detox
in specs; no `TestHelpers.delay()`; proper timeouts and descriptions.
- **Relay / transaction-pay**
- Mainnet USDC→mUSD quote mock and
`mockRelayQuoteMainnetMusd(mockServer)` in
`tests/api-mocking/mock-responses/transaction-pay.ts` so confirmation
screen gets a valid quote (avoids “No quotes”).

All three tests use local Anvil (no mainnet fork), `setupMusdMocks`, and
end with Activity tab verification of the confirmed mUSD conversion.

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

## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because it modifies shared E2E infrastructure
(`FixtureBuilder`, Relay quote mocks, and scrolling helpers), which
could introduce flakiness or break unrelated tests despite being
non-production code.
> 
> **Overview**
> Adds a new E2E suite that validates the **mUSD conversion happy path**
across first-time, token-list, and asset-overview entry points,
asserting the resulting Activity row is confirmed.
> 
> Introduces dedicated mUSD test infrastructure: a reusable
`createMusdFixture` helper plus `FixtureBuilder.withMusdConversion()` to
seed Mainnet balances/state, and a full set of API mocks (feature flags,
geo/ramp, price/token APIs, Merkl rewards, Relay quote/status) backed by
shared `USDC_MAINNET`/`MUSD_MAINNET` constants.
> 
> Extends page objects to support the flow (`WalletView` CTAs +
scrolling, `TransactionPayConfirmation.enterAmountAndContinue`,
`ActivitiesView.verifyMusdConversionConfirmed`) and tightens
`TrendingView` feed scrolling to use `scrollToElement` with configurable
timeouts. Also adds a Mainnet-specific Relay quote mock
(`mockRelayQuoteMainnetMusd`) to keep Transaction Pay confirmations from
failing with missing quotes.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
66af719. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Javier Garcia Vera <javier.vera@consensys.net>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

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

Code owners update for new token details 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: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: only updates CODEOWNERS review ownership with no runtime
code changes; impact is limited to PR review routing/enforcement for
`TokenDetails`.
> 
> **Overview**
> Updates `.github/CODEOWNERS` to add `app/components/UI/TokenDetails`
under **Assets Team** (`@MetaMask/metamask-assets`), ensuring code owner
review is required for changes in that UI area.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
692dc03. 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 removes the usage of the selector
`selectMultichainAccountsState2Enabled` which gets the value for the
BIP-44 feature flag. Moving forward, BIP-44 is the default behaviour and
any alternative logic branch will be remove alongside tests.

The scope of the changes is limited to files inside the
`app/components/UI/` directory.

## **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/MUL-1382

## **Manual testing steps**

Not applicable

## **Screenshots/Recordings**

Not applicable

## **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**
> Removes legacy/flagged UI branches and changes user-visible behavior
(e.g., `AddressCopy` no longer copies to clipboard and network selector
defaults/sections change). Moderate risk of regressions in navigation,
balance display, and tests due to widened unconditional paths.
> 
> **Overview**
> **Standardizes UI on multichain/BIP-44 behavior by removing
`selectMultichainAccountsState2Enabled` gating.**
> 
> `AddressCopy` is simplified to no longer accept an `account` prop and
no longer performs clipboard/toast/metrics/protect-wallet logic;
pressing the icon now always navigates to the multichain address list
(updated call sites in `Navbar` and `AccountInfo`, plus a simplified
test).
> 
> Network selection UI is de-flagged: `NetworkManager`’s initial tab
selection is now derived solely from `enabledNetworksByNamespace`,
`NetworkMultiSelector` always renders the custom network section for any
namespace, and `NetworkMultiSelectorList` always prepends the “select
all networks” row when provided.
> 
> `AssetOverview` drops the state2-specific balance shortcut and always
uses `asset.balance` when present; tests are updated accordingly (mock
selectors refactor, Solana balance expectation, and an updated “no
balance” scenario).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0516e6e. 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**
The token-search-discovery-controller was used by mobile at some point
to get data from the portfolio API, after investigating its use I
concluded that this controller could be fully removed from the codebase.
I will follow up with a PR that removes it from
[core](MetaMask/core#7789)
<!--
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: removed usage of token-search-discovery-controller

## **Related issues**

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

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk cleanup that removes an unused controller and associated
hook/tests; main risk is any remaining hidden runtime dependency on
`TokenSearchDiscoveryController` now removed from Engine context/state
and dependencies.
> 
> **Overview**
> Removes the legacy `TokenSearchDiscoveryController` integration
end-to-end: its Engine initialization/context wiring, messenger + init
module, selectors, and the `useTokenSearchDiscovery` hook/tests.
> 
> Cleans up persisted/background state and logging snapshots to no
longer include `TokenSearchDiscoveryController`, and drops the
`@metamask/token-search-discovery-controller` dependency from
`package.json`/`yarn.lock` (while keeping
`TokenSearchDiscoveryDataController` in place).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
91b82ee. 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**
The marketing team has asked for a deeplink to the NFTs screen/tab.
After researching other components I found two kind of behaviors (taking
users to the NFTs tab or taking users to the NFTs screen) and raised the
question to the marketing team:
<img width="993" height="153" alt="image"
src="https://github.com/user-attachments/assets/5d0d43b6-46e6-493d-8b15-c109f0f28ee4"
/>

Here is the video I attached them (Sound ON):

https://github.com/user-attachments/assets/f7b563c2-8d54-4e77-8297-662469828a6e

Here is their response:
<img width="1134" height="107" alt="image"
src="https://github.com/user-attachments/assets/2e89c924-1d5c-4624-844a-6702bf00a7a7"
/>

Therefore we will be navigating to the NFTs screen (not tab) whenever
the deeplink is opened


<!--
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 deeplinking to the NFT screen

## **Related issues**

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

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**


https://github.com/user-attachments/assets/a826ef60-6f5c-4493-8616-c68d739d69c8


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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: adds a new deeplink route and handler that only performs
in-app navigation plus analytics route mapping, with tests covering the
new handler’s error paths.
> 
> **Overview**
> Adds support for the `/nft` universal link action so marketing links
like `https://link.metamask.io/nft` navigate directly to the NFTs full
view.
> 
> Wires the new `ACTIONS.NFT` through `handleUniversalLink`, the
supported-action/type lists, and deep-link analytics route
extraction/mapping (no sensitive params extracted). Includes unit tests
for `handleNftUrl`, including fallback navigation to
`Routes.WALLET.HOME` on errors.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c77e32b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…4.0 (#25385)

## **Description**

Improves analytics data quality by returning the actual domain host for
known public RPC providers instead of masking them as 'custom'.

- Add `isPublicRpcDomain` helper in `rpc-domain-utils.ts` that checks if
an RPC URL has a known public domain
- Simplify `isPublicEndpointUrl` by using the new helper
- `sanitizeRpcUrl` now returns the actual host (e.g.,
`mainnet.infura.io`, `eth-mainnet.alchemyapi.io` or any RPC from
chainid.network) for known public domains, improving the accuracy of
`rpc_domain` in analytics events

## **Changelog**

CHANGELOG entry: null

## **Related issues**

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

## **Manual testing steps**

```gherkin
Feature: RPC domain analytics

  Scenario: Verify rpc_domain shows actual host when switching to public RPC via banner
    # Setup - Add Ink network with local RPC
    Given user navigates to Settings → Networks → Add Network
    And user adds Ink network (Chain ID: 57073) with local RPC endpoint: http://127.0.0.1:8545
    And user also adds public RPC endpoint: https://rpc-qnd.inkonchain.com
    And user sets the local RPC as the default endpoint
    And user switches to Ink network
    
    # Trigger degraded state
    When user disconnects local RPC (or it becomes unavailable)
    And user waits for banner showing "Still connecting to Ink..."
    
    # Trigger RPC update from banner
    Then the "Update RPC" button appears on the banner
    When user clicks "Update RPC" on the banner
    And user is navigated to Edit Network screen
    And user switches default RPC to https://rpc-qnd.inkonchain.com
    
    # Verify analytics in Segment
    When user checks Segment dashboard for "Network Connection Banner RPC Updated" event
    Then the event property from_rpc_domain should be "custom" (local RPC is private)
    And the event property to_rpc_domain should be "rpc-qnd.inkonchain.com" (known public domain)

  Scenario: Verify rpc_domain for Infura networks using Switch to MetaMask default
    # Setup - Configure Arbitrum with local RPC
    Given user starts a local Ganache server: npx ganache --chain.chainId 42161
    And user navigates to Settings → Networks → Arbitrum One
    And user adds a new RPC endpoint: http://127.0.0.1:8545
    And user sets the local RPC as the default endpoint
    
    # Trigger degraded state
    When user stops the Ganache server (Ctrl+C)
    And user waits for banner showing "Still connecting to Arbitrum One..."
    
    # Switch to Infura via banner button
    Then the "Switch to MetaMask default RPC" button appears on the banner
    When user clicks "Switch to MetaMask default RPC"
    Then the toast "Updated to MetaMask default" appears
    
    # Verify analytics
    When user checks Segment for "Network Connection Banner Switch To MetaMask Default RPC Clicked"
    Then rpc_domain should be "custom" (the local RPC being switched from)
```

## **Screenshots/Recordings**

N/A - Internal analytics improvement, no UI changes.

### **Before**

### **After**

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes the logic that decides whether an RPC URL is safe to include
in analytics, which could affect privacy/data reporting if domains are
misclassified. Also adds a new async initialization step during `Engine`
startup (non-blocking) that reports failures to Sentry.
> 
> **Overview**
> Improves RPC-domain analytics by recognizing *known public RPC
provider domains* (e.g., Infura/Alchemy and domains learned from cached
safe-chain RPC lists) as safe to report, so metrics can record the real
host instead of lumping these under `custom`.
> 
> Adds `isPublicRpcDomain` to `rpc-domain-utils` and wires it into
`isPublicEndpointUrl` in network-controller utilities; `Engine` now
asynchronously preloads the provider-domain cache on startup and
captures init errors via Sentry. Updates unit tests to cover
invalid/localhost URLs and known public provider domains.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7d9f601. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**
This PR extends the `TRENDING_FEED_VIEWED` analytics event with an
`interaction_type` discriminator pattern to track detailed user
interactions within the Trending feed.

Related: Consensys/segment-schema#440

### Background
The existing `TRENDING_FEED_VIEWED` event (PR #23674) tracks
session-level metrics (session_id, session_time, entry_point,
is_session_end). This PR adds granular interaction tracking.

### Changes
1. **Added `interaction_type` discriminator** - All events now include
an `interaction_type` field to distinguish between: `session_start`,
`session_end`, `token_click`, `search`, `filter_change`

2. **Token Click Tracking** - Tracks when users tap on tokens from the
Trending feed, including position, price data, and active filter context

3. **Search Tracking** - Tracks search queries with debounce (500ms),
including result counts and filter context

4. **Filter Change Tracking** - Tracks when users change time, sort, or
network filters, including previous and new values

5. **Filter Context Propagation** - Added `TrendingFilterContext`
interface and propagated it through `TrendingTokensList` →
`TrendingTokenRowItem` for analytics context

---

# Debug Console Logs for Testing

Temporary console.logs have been added to help verify the events fire
correctly.

**File:**
`app/components/UI/Trending/services/TrendingFeedSessionManager.ts`

### Session Start/End (in `trackEvent` method, after line 256):
```typescript
// Add after: const analyticsProperties = { ... };
console.log(
  `${isSessionEnd ? '🛑' : '🚀'} TRENDING_FEED_VIEWED [${interactionType}]`,
  analyticsProperties,
);
```

### Token Click / Search / Filter Change (in `trackInteraction` method,
after line 296):
```typescript
// Add after: const analyticsProperties = { ... };
const emoji = {
  token_click: '🔥',
  search: '🔍',
  filter_change: '⚙️',
}[interactionType] || '📊';
console.log(`${emoji} TRENDING_FEED_VIEWED [${interactionType}]`, analyticsProperties);
```
## New Analytics Attributes

### Interaction Types

| `interaction_type` | Description |
|--------------------|-------------|
| `session_start` | Fired when user enters Trending feed |
| `session_end` | Fired when user leaves Trending feed |
| `token_click` | Fired when user taps on a token |
| `search` | Fired when user searches (debounced 500ms) |
| `filter_change` | Fired when user changes time/sort/network filter |

### Token Click Properties (when `interaction_type = token_click`)

| Property | Type | Description |
|----------|------|-------------|
| `token_symbol` | string | Token symbol clicked (e.g., "ETH") |
| `token_address` | string | Token contract address |
| `token_name` | string | Token display name |
| `chain_id` | string | Network chain ID (hex format) |
| `position` | integer | 0-indexed position in list |
| `price_usd` | number | Token price at click time (USD) |
| `price_change_pct` | number | Price change percentage |
| `time_filter` | string | Active time filter (e.g., "24h", "6h", "1h",
"5m") |
| `sort_option` | string | Active sort option (e.g., "price_change",
"volume") |
| `network_filter` | string | Active network filter ("all" or chain ID)
|
| `is_search_result` | boolean | Was this from search results? |

### Search Properties (when `interaction_type = search`)

| Property | Type | Description |
|----------|------|-------------|
| `search_query` | string | The search query entered |
| `results_count` | integer | Number of results returned |
| `has_results` | boolean | Whether search returned any results |
| `time_filter` | string | Active time filter |
| `sort_option` | string | Active sort option |
| `network_filter` | string | Active network filter |

### Filter Change Properties (when `interaction_type = filter_change`)

| Property | Type | Description |
|----------|------|-------------|
| `filter_type` | string | Type of filter changed: "time", "sort", or
"network" |
| `previous_value` | string | Previous filter value |
| `new_value` | string | New filter value |
| `time_filter` | string | Active time filter |
| `sort_option` | string | Active sort option |
| `network_filter` | string | Active network filter |

---

## **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: Trending Feed Analytics Tracking

  Scenario: User clicks on a token from Trending feed
    Given the user is on the Trending feed (via homepage or Trade button)
    When user taps on a token in the list
    Then a TRENDING_FEED_VIEWED event fires with interaction_type="token_click"
    And the event includes token_symbol, position, price data, and filter context
    And console shows "🔥 TRENDING_FEED_VIEWED [token_click]" with properties

  Scenario: User searches for a token
    Given the user is on the Trending full view
    When user types a search query and waits 500ms
    Then a TRENDING_FEED_VIEWED event fires with interaction_type="search"
    And the event includes search_query, results_count, and has_results
    And console shows "🔍 TRENDING_FEED_VIEWED [search]" with properties

  Scenario: User changes the time filter
    Given the user is on the Trending full view with 24h filter active
    When user changes the time filter to 6h
    Then a TRENDING_FEED_VIEWED event fires with interaction_type="filter_change"
    And filter_type="time", previous_value="24h", new_value="6h"
    And console shows "⚙️ TRENDING_FEED_VIEWED [filter_change]" with properties

  Scenario: User changes the network filter
    Given the user is on the Trending full view with "all" networks
    When user selects a specific network (e.g., Ethereum)
    Then a TRENDING_FEED_VIEWED event fires with interaction_type="filter_change"
    And filter_type="network" with previous and new chain IDs
    And console shows "⚙️ TRENDING_FEED_VIEWED [filter_change]" with properties

  Scenario: Session tracking includes interaction_type
    Given the user opens the Trending feed
    Then a TRENDING_FEED_VIEWED event fires with interaction_type="session_start"
    And console shows "🚀 TRENDING_FEED_VIEWED [session_start]"
    When user navigates away from Trending
    Then a TRENDING_FEED_VIEWED event fires with interaction_type="session_end"
    And console shows "🛑 TRENDING_FEED_VIEWED [session_end]"
```

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

Uploading Screen Recording 2026-01-29 at 17.35.57.mov…


## **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**
> Medium risk because it changes tab-switching behavior via a new
`onLeave` hook and adds new analytics side effects (session start/end,
search debounce) across multiple Trending entry points, which could
impact navigation timing and event volume.
> 
> **Overview**
> **Expands Trending analytics from session-only to interaction-level
tracking.** `TrendingFeedSessionManager` now emits
`TRENDING_FEED_VIEWED` events with an `interaction_type` discriminator
(start/end, token_click, search, filter_change) and exposes new tracking
helpers.
> 
> Trending UI now propagates a `TrendingFilterContext` through
`TrendingTokensList`/`TrendingTokenRowItem` to record token click
position, pricing, and active filters, adds a debounced
`useSearchTracking` hook for search events (used in both the full
Trending tokens view and Explore search), and tracks filter changes when
time/sort/network selections change.
> 
> Navigation updates add a tab-level `onLeave` callback and invoke it on
tab switches; the Trending tab uses this to start sessions on press and
end sessions when leaving the tab.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
dbfeda0. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

This PR updates the General Settings page and SelectComponent modal to
use the `HeaderCenter` component for consistent header styling across
the app.

**Changes:**
1. **GeneralSettings page**: Replaced the dynamic navigation header
(`getNavigationOptionsTitle`) with an inline `HeaderCenter` component,
following the pattern established in the parent Settings page
2. **Navigation config**: Set `headerShown: false` at the stack level
for GeneralSettings screens in MainNavigator.js
3. **SafeAreaView**: Wrapped GeneralSettings content in `SafeAreaView`
for proper safe area handling
4. **SelectComponent modal**: Updated the "Base currency" (and other
select) modal header to use `HeaderCenter` with a close button

## **Changelog**

CHANGELOG entry: Updated General Settings page and select modal headers
to use consistent HeaderCenter component styling

## **Related issues**

Fixes:
https://consensyssoftware.atlassian.net/jira/software/c/projects/MDP/boards/2972?assignee=62afb43d33a882e2be47c36f&quickFilter=3325&selectedIssue=MDP-697

## **Manual testing steps**

```gherkin
Feature: General Settings Header

  Scenario: User navigates to General Settings
    Given the user is on the Settings page

    When user taps on "General"
    Then the General Settings page opens with a centered "General" title header
    And a back arrow button is visible on the left

  Scenario: User opens currency selector modal
    Given the user is on the General Settings page

    When user taps on the currency dropdown
    Then a modal opens with "Base currency" as the centered title
    And a close (X) button is visible on the right
    When user taps the close button
    Then the modal closes
```

## **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/b75d366c-2479-42da-a9b0-459eef386c99

<!-- [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/navigation refactor that mainly changes header rendering
and related tests; minimal impact to underlying settings behavior.
> 
> **Overview**
> **Unifies header UI for General Settings and select modals.**
`GeneralSettings` now renders its own `HeaderCenter` (wrapped in
`SafeAreaView`) instead of configuring a React Navigation header, and
`MainNavigator` forces `headerShown: false` for `GeneralSettings`
screens.
> 
> `SelectComponent`’s modal header is replaced with `HeaderCenter` (adds
close button handling). Tests were migrated from Enzyme to Testing
Library and snapshots updated to reflect the new header structure and
navigation interactions.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
95f4c98. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
….0 cp-7.62.2 (#25438)

## **Description**

Complete the 429 rate limiting fix for position management operations.
The previous fix (commit `425beaead7`) only addressed
`updatePositionTPSL()`. This PR extends the fix to `closePosition()`,
`closePositions()`, and `updateMargin()` methods.

**Problem:** These methods were using `skipCache: true` which forced
REST API calls on every operation, leading to 429 rate limiting errors
during prolonged app usage.

**Solution:**
- Remove `skipCache: true` from `closePositions()` and `updateMargin()`
to use WebSocket cache
- For `closePosition()`, add optional `position` parameter so callers
can pass the live WebSocket position directly, avoiding the need to
fetch positions entirely
- Update `usePerpsClosePosition` hook to pass the position it already
has

## **Changelog**

CHANGELOG entry: Fixed rate limiting errors (429) when closing positions
or updating margin after prolonged app usage

## **Related issues**

Fixes: Rate limiting issues during position close/margin update
operations


## **Manual testing steps**

```gherkin
Feature: Position close without rate limiting

  Scenario: User closes position after prolonged usage
    Given user has the app open for extended period (>30 minutes)
    And user has an open perps position

    When user closes the position
    Then the position closes successfully without 429 errors

  Scenario: User updates margin after prolonged usage
    Given user has the app open for extended period (>30 minutes)
    And user has an open perps position with isolated margin

    When user adjusts the margin
    Then the margin updates successfully without 429 errors

  Scenario: User closes all positions
    Given user has multiple open perps positions

    When user uses "close all positions" feature
    Then all positions close successfully without rate limiting errors
```

## **Screenshots/Recordings**

### **Before**

N/A - Bug fix for rate limiting, no UI changes

### **After**

N/A - Bug fix for rate limiting, no UI changes

## **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 perps position-management flows (`closePosition`,
`closePositions`, `updateMargin`) and changes them to rely on
cached/WebSocket position data, which could surface edge cases if the
cache is stale or mismatched, but does not alter core order-placement
logic.
> 
> **Overview**
> Reduces 429 errors in perps position management by stopping forced
REST position refreshes during `closePositions` and `updateMargin`, and
by updating `closePosition` to accept an optional live `position`
payload (with a cache-based fallback).
> 
> Updates `usePerpsClosePosition` (and its tests) to pass the
already-available position through, avoiding extra `getPositions()`
calls during close flows.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ccfc17e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Michal Szorad <michal.szorad@consensys.net>
@pull pull Bot locked and limited conversation to collaborators Jan 30, 2026
@pull pull Bot added the ⤵️ pull label Jan 30, 2026
@pull pull Bot merged commit 6f89dec into Reality2byte:main Jan 30, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.