Skip to content

[pull] main from MetaMask:main#552

Merged
pull[bot] merged 24 commits into
Reality2byte:mainfrom
MetaMask:main
Feb 25, 2026
Merged

[pull] main from MetaMask:main#552
pull[bot] merged 24 commits into
Reality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Feb 25, 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 : )

dan437 and others added 24 commits February 25, 2026 12:08
## **Description**

Adds metrics for predict withdraw transactions as part of the MM Pay
metrics framework.

## **Changelog**

CHANGELOG entry: Adds metrics for predict withdraw transactions as part
of the MM Pay metrics

## **Related issues**

Fixes: MetaMask/MetaMask-planning#7033

## **Manual testing steps**

```gherkin
Feature: Predict withdraw metrics

  Scenario: user initiates a predict withdraw
    Given user has funds in their predict account

    When user initiates a predict withdraw to any token
    Then transaction events include mm_pay_use_case = 'predict_withdraw'
    And transaction events include mm_pay_sending_value_usd with the USD value of the withdraw amount
    And transaction events include mm_pay_receiving_value_usd with the USD value of the expected receive amount
    And child transactions (relay deposits) inherit the USD value metrics from the parent
```

## **Screenshots/Recordings**

### **Before**

N/A — metrics-only change

### **After**

N/A — metrics-only 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
- [ ] 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**
> Metrics-only changes that add new event properties and copy logic
without affecting transaction execution or user-facing flows.
> 
> **Overview**
> Adds **MetaMask Pay metrics support for
`TransactionType.predictWithdraw`** by emitting `mm_pay_use_case:
"predict_withdraw"` from `useTransactionPayMetrics`.
> 
> When a pay token is selected, the hook now also records
USD-denominated amounts via `mm_pay_sending_value_usd` (from required
token `amountUsd`, defaulting to `0`) and `mm_pay_receiving_value_usd`
(from quote totals `targetAmount.usd`, or `null` if unavailable).
> 
> Extends engine-side MetaMetrics copying so child bridge/swap
transactions can inherit `mm_pay_sending_value_usd` and
`mm_pay_receiving_value_usd` from a `predictWithdraw` parent, with
new/updated unit tests covering these cases.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0bfbabe. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Signed-off-by: dan437 <80175477+dan437@users.noreply.github.com>
…ENV variable (#26260)

## **Description**

Moves withdraw token filtering configuration from the flat
`confirmations_pay` feature flag to a new version-gated
`confirmations_pay_post_quote` flag with a `default`/`override`
structure keyed by transaction type (e.g. `predictWithdraw`,
`perpsWithdraw`).

Override entries fully replace matching default properties (via `??`
fallback), so each transaction type can independently control `enabled`
and `tokens` while inheriting unset properties from `default`.

The withdraw token picker now builds its list from the allowlist rather
than filtering account tokens down — tokens the user doesn't hold are
resolved from the `TokenListController` catalog (ERC20s) or network
config (native tokens), ensuring allowlisted tokens appear even with a
zero balance.

Both the `MM_PREDICT_WITHDRAW_ANY_TOKEN` env var and the remote feature
flag `enabled` must be true for the feature to activate.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: MetaMask/MetaMask-planning#6970

## **Manual testing steps**

```gherkin
Feature: Withdraw token filtering via remote feature flag

  Scenario: user sees allowlisted tokens in withdraw token picker
    Given the user has a Predict Withdraw transaction pending
    And the confirmations_pay_post_quote feature flag is enabled with a tokens allowlist
    And MM_PREDICT_WITHDRAW_ANY_TOKEN=true in .js.env

    When user opens the "Select receive token" modal
    Then only tokens matching the allowlist are shown
    And tokens from the allowlist that the user does not hold appear with zero balance

  Scenario: override config takes precedence for predictWithdraw
    Given the feature flag has a default tokens list and a predictWithdraw override with different tokens
    And the transaction type is predictWithdraw

    When user opens the "Select receive token" modal
    Then the override's token list is used instead of the default

  Scenario: feature is disabled when env var is not set
    Given MM_PREDICT_WITHDRAW_ANY_TOKEN is not set or false
    And the feature flag enabled is true

    When user opens a Predict Withdraw confirmation
    Then the "Select receive token" picker is not available
```

## **Screenshots/Recordings**

### **Before**

### **After**

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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 token-listing and selection behavior for withdraw
confirmations and adds side effects (auto-tracking tokens) plus new
feature-flag plumbing; mistakes could hide tokens or misconfigure
post-quote flows.
> 
> **Overview**
> Withdraw token selection is now driven by a new versioned remote flag,
`confirmations_pay_post_quote`, with `default` + per-transaction-type
`overrides` resolved via a new `selectPayQuoteConfig` selector and
`getPostQuoteTransactionType` helper.
> 
> In the Pay-with/Receive token modal, withdraw flows now use a
dedicated `useWithdrawTokenFilter` allowlist (fed from the full token
catalog via `includeAllTokens`) instead of `getAvailableTokens`, and
selecting a zero-balance ERC-20 during withdraw proactively tracks it in
`TokensController` so metadata can be resolved.
> 
> This removes the `MM_PREDICT_WITHDRAW_ANY_TOKEN` env var toggle and
adds/updates unit tests around override behavior, allowlist filtering
(including native-token zero-address matching), and catalog-backed
zero-balance tokens.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e6c6656. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Signed-off-by: dan437 <80175477+dan437@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**
Add a environment toggle in rc builds:
https://consensyssoftware.atlassian.net/browse/RWDS-1045
<!--
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**



https://github.com/user-attachments/assets/f92f77be-26a0-4f35-a7b8-6e25e5b12a7f


<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-02-19 at 14 50 26"
src="https://github.com/user-attachments/assets/db6bc745-ed38-41be-a0dd-cc0da771229c"
/>

<!-- [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**
> Touches RewardsController/DataService request routing and state
persistence; incorrect gating or reset behavior could point clients at
the wrong backend or leave Rewards data inconsistent across environment
switches.
> 
> **Overview**
> Adds a new `RewardsEnvironmentToggle` to the Rewards settings footer,
allowing eligible (non-production/RC-allowed) builds to switch the
Rewards API base URL via a bottom sheet and mark the build-default URL.
> 
> Threads the override through the Engine: `RewardsController` now
persists `rewardsEnvUrl`, exposes `get/canChange/set/getDefault` env
actions, preserves `rewardsEnvUrl` across `resetState`, and synchronizes
changes to `RewardsDataService`, which now supports guarded URL
overrides and uses `getRewardsEnvUrl()` per request.
> 
> On env switch, the UI triggers a reset flow (cancels bulk-link, clears
Redux rewards slice, and forces candidate subscription refetch) to avoid
stale cross-environment data; adds i18n strings and comprehensive unit
tests/snapshot updates to cover the new behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0436fd7. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Rik Van Gulck <vangulckrik@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## **Description**

Addresses 5 confirmed Bugbot findings from [Core PR
#7941](MetaMask/core#7941).

### What changed

1. **Missing 'canceled' spelling** — deposit+order `.catch()` only
checked `'cancelled'`, not `'canceled'`
2. **Cancelled deposits stay pending** — non-placeOrder cancellation
cleared UI state but left the deposit request as `'pending'`
3. **Stale `activeProviderInstance` after disconnect** — standalone
reads could route through a disconnected provider
4. **Disconnect skips preload teardown** — preload timer and messenger
subscriptions were not stopped, causing background work during teardown
5. **Analytics side effect inside immer producer** — `trackPerpsEvent()`
and `#debugLog()` moved out of `this.update()`

### Disconnect design note

Fix 4 inlines the preload cleanup logic from `stopMarketDataPreload()`
rather than calling it directly, because `stopMarketDataPreload()` calls
`#cleanupStandaloneProvider()` fire-and-forget, while `disconnect()`
needs the awaited version to prevent races with reconnection.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: Bugbot findings on MetaMask/core#7941

## **Manual testing steps**

```gherkin
Feature: Perps deposit cancellation and disconnect cleanup

  Scenario: user cancels a deposit transaction
    Given user is on the Perps deposit screen with a pending deposit

    When user rejects the transaction in the wallet prompt
    Then the deposit request status should be 'cancelled' (not stuck as 'pending')

  Scenario: user disconnects from Perps
    Given user is on Perps screens with active market data preload

    When user navigates away triggering disconnect
    Then preload timer is stopped, provider instance is nulled, and no stale subscriptions remain
```

## **Screenshots/Recordings**

N/A — internal controller logic, 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 deposit/withdrawal status transitions and disconnect teardown
ordering, which can affect transaction UX, metrics emission, and
background polling behavior if regressions occur.
> 
> **Overview**
> Fixes several PerpsController lifecycle edge cases around deposits,
withdrawals, and teardown.
> 
> Deposit tracking now correctly treats both `cancelled` and `canceled`
error strings as user cancellation, and ensures non-order deposit
cancellations update the corresponding `depositRequests` entry to
`cancelled` instead of leaving it `pending`.
> 
> `updateWithdrawalStatus` no longer performs analytics/logging
side-effects inside the `this.update()` immer producer; it computes
whether tracking/logging is needed during the state update and runs
`trackPerpsEvent`/`#debugLog` afterward.
> 
> `disconnect()` now proactively stops market-data preload intervals and
unsubscribes messenger listeners, resets cached preload config, clears
`activeProviderInstance` to avoid stale routing, and awaits
standalone-provider cleanup. A new unit test asserts preload work does
not continue after disconnect.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
330b560. 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**

Update transaction-controller to version 62.19.0 for renamed
launchdarkly flag for incoming transaction improvements.

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Dependency upgrade touches transaction controller codepaths and
updates multiple transitive controller packages, which could affect
transaction handling and network/account interactions despite minimal
app-code changes.
> 
> **Overview**
> Updates `@metamask/transaction-controller` from `^62.18.0` to
`^62.19.0`, pulling in upstream changes (notably a renamed LaunchDarkly
flag related to incoming transaction improvements).
> 
> Regenerates `yarn.lock`, which also shifts several transitive MetaMask
controller versions (e.g., `@metamask/accounts-controller`,
`@metamask/core-backend` and related network/profile dependencies) and
pins `@tanstack/react-query` back to `5.90.20`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2ccefe2. 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**

## E2E: Increase timeout for Activity/Wallet taps in mUSD conversion
happy path

Toast visibility is unreliable: it may or may not be present, and can
appear right when tapping Activity. Rather than adding toast-specific
handling, we only increase the retry timeout for `tapActivity` and
`tapWallet` in this flow. With a longer timeout (30s), retries have more
time to succeed once the toast has dismissed or the UI has settled.
<!--
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**
> Test-only changes that only adjust retry timeouts/parameters; no
production logic or data handling is affected.
> 
> **Overview**
> Reduces flakiness in the mUSD conversion happy-path smoke test by
allowing `TabBarComponent.tapActivity` and `tapWallet` to accept an
optional `timeout` and wiring those calls to use a longer 30s retry
window.
> 
> This keeps the existing retry/validation behavior but makes the
timeout configurable so the test can tolerate transient UI interference
(e.g., toasts) when switching between Wallet and Activity.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b6b797f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
… checks (#26475)

## **Description**

Issues created in GitHub by the **issuebridge** app are Jira issues
created by humans, mirrored in GitHub. The GitHub actor is
`issuebridge`, so the "Check template and add labels" action was calling
`userBelongsToMetaMaskOrg(octokit, 'issuebridge')`. The GraphQL
`user(login:)` API does not resolve GitHub App logins as users, so the
request
[failed](https://github.com/MetaMask/metamask-mobile/actions/runs/22314947902/job/64557062284)
with "Could not resolve to a User with the login of 'issuebridge'."

**Change:** Introduce a separate list `loginsExemptFromOrgCheck` (e.g.
`issuebridge`) for actor logins that are not resolvable as User in
GraphQL. For these we only skip the org check and do not add the
external-contributor label; we do **not** treat them as full bots. All
other behaviour runs: template matching, invalid-template label,
regression labels, needs-triage, etc., so issuebridge-created
(Jira-mirrored) issues get the same checks and labels as human-created
issues.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

NA

## **Manual testing steps**

1. Create an issue in Jira and wait for `issuebridge` app to mirror it
on GitHub (or use this [existing test
issue](#26405))
2. Update issue description
3. Go to
[check-template-and-add-labels](https://github.com/MetaMask/metamask-mobile/actions/workflows/check-template-and-add-labels.yml)
GitHub Action
4. Confirm the workflow succeeds

## **Screenshots/Recordings**

NA

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk workflow-script change that only alters how the
external-contributor label decision is made for a specific app login; it
doesn’t affect runtime product code.
> 
> **Overview**
> Prevents the `check-template-and-add-labels` GitHub Action from
failing on GitHub App logins (e.g. `issuebridge`) that cannot be
resolved via GraphQL `user(login:)`.
> 
> Adds `loginsExemptFromOrgCheck` and updates the external-contributor
labeling condition to skip the MetaMask org membership lookup for these
actors, while still running the usual template validation and labeling
logic for their issues/PRs.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
cd5b950. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Cursor <cursoragent@cursor.com>
…d` fixture (#26488)

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

Remove BIP-44 State 2 mock
(remoteFeatureMultichainAccountsAccountDetailsV2) for Multichain account
E2E 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: null

## **Related issues**

Fixes: None

## **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]
> **Low Risk**
> Test-only refactor that removes a single mock hook; risk is limited to
potential E2E flakiness/behavior changes if the default feature-flag
state differs from the previously forced value.
> 
> **Overview**
> Multichain account E2E tests using
`withMultichainAccountDetailsEnabledFixtures` no longer inject a remote
feature-flag mock to explicitly disable Account Details V2.
> 
> This simplifies the fixture setup by removing the `testSpecificMock`
wiring, leaving only the base fixture build + app restart/login flow;
V2-specific tests continue to enable V2 via
`withMultichainAccountDetailsV2EnabledFixtures`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a6806a6. 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**
- Migrated tests/framework/fixtures/performance-test.js to TypeScript
under tests/framework/fixtures/performance/
- Split into performance-fixture.ts (fixture logic) and index.ts (barrel
exports) for better scalability
- Extracted getTeamInfoFromTags into a typed utility at
tests/framework/utils/teams.ts, importing TEAMS from the existing
   tests/teams-config.js
- Updated imports across all 18 performance test spec files
- Deleted the old JS fixture

Run reference:
https://github.com/MetaMask/metamask-mobile/actions/runs/22355406982

<!--
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**
> Primarily a test-only refactor (file moves, import rewrites, and added
typing) with minimal behavioral change; main risk is broken test imports
or fixture wiring causing performance runs to fail.
> 
> **Overview**
> Migrates the performance test fixture from a single JS module to a
typed TypeScript fixture under `tests/framework/fixtures/performance/`,
adding a barrel `index.ts` export and updating all performance
specs/docs to import from the new path.
> 
> Extracts team-tag parsing into a new typed helper
`tests/framework/utils/teams.ts` and updates `PerformanceReporter` (and
its tests) to use it; `tests/teams-config.js` is reduced to exported
constants (`TEAMS`, `DEFAULT_TEAM_TAG`).
> 
> The new TS fixture tightens types and error handling around metric
attachment, quality-gate failures (to skip retries), and session-id
extraction/attachment.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f137c86. 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?
-->

https://consensyssoftware.atlassian.net/browse/RWDS-1027
Allow user to redeem a bonus code in WaysToEarn 

## **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: Allow user to redeem a bonus code in WaysToEarn 


## **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**
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-02-13 at 15 09 15"
src="https://github.com/user-attachments/assets/ae439ae7-13dd-4b74-9b4e-541a9b21ae2e"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-02-13 at 15 09 05"
src="https://github.com/user-attachments/assets/a2a5de6c-41c2-48fb-8001-04786ad42ed7"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-02-13 at 17 08 22"
src="https://github.com/user-attachments/assets/7b3f311b-3633-4257-8354-d1b9a7d889cf"
/>
<img width="1179" height="2556" alt="Simulator Screenshot - E2E Test -
2026-02-13 at 17 16 26"
src="https://github.com/user-attachments/assets/5e85eede-47c9-4ca0-99dd-43a524924187"
/>

<!-- [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**
> Introduces new navigation/modal flow and new Engine controller calls
for bonus code validate/apply; behavior changes to referral validation
could affect existing referral-code entry and needs regression testing
around edge cases and localization.
> 
> **Overview**
> Adds a dedicated **Bonus Code** redemption flow in Rewards: selecting
a `BONUS_CODE` item in *Ways to Earn* now opens a new
`BonusCodeBottomSheet` modal (wired via new
`Routes.MODAL.REWARDS_BONUS_CODE_BOTTOM_SHEET` and registered in
`MainNavigator`) that validates the code and submits it to
`RewardsController:applyBonusCode`, showing success/error UI and a
toast.
> 
> Extends Rewards activity/event rendering to recognize `BONUS_CODE`
events (new `BonusCodeEventDetails`, updated `ActivityDetailsSheet`
dispatch, and `eventDetailsUtils` details extraction) and expands error
mapping in `handleRewardsErrorMessage` for bonus-code-specific server
messages.
> 
> Tightens referral code UX by enforcing `REFERRAL_CODE_LENGTH` via
`maxLength` and refactors `useValidateReferralCode` to validate
immediately with stale-response protection (removing lodash debounce),
with test updates across the new/changed behaviors.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9a95083. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Rik Van Gulck <vangulckrik@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.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**
update buidls yml with missing quicknode networks urls
<!--
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**
> Config-only change that adds new secret keys; low risk aside from
potential CI/runtime failures if the new secrets aren’t populated in the
target GitHub environments.
> 
> **Overview**
> Adds two missing QuickNode secret mappings in `builds.yml`:
`QUICKNODE_BSC_URL` and `QUICKNODE_SEI_URL`, so CI/local builds can
consume these network RPC URLs via GitHub Secrets like the other
QuickNode endpoints.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
836e35a. 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 a variant-based override to fullscreen confirmation logic so mUSD
quick convert (variant=quickConvert) stays in the bottom-sheet
confirmation flow.
- Updates useFullScreenConfirmation to read route params and apply
`FORCE_BOTTOM_SHEET_BY_VARIANT` for targeted transaction/variant
combinations.
- Prevents the confirmation loader from rendering for bottom-sheet
confirmations when approvalRequest is not yet available.

These changes are necessary since mUSD conversions will have more than
one confirmation for the same transaction type.
<!--
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: updated full-screen confirmation/loading for mUSD Quick
Convert by forcing that variant to use the bottom-sheet flow.

## **Related issues**

- Jira ticket: [MUSD-150: Quick convert proof of
concept](https://consensyssoftware.atlassian.net/browse/MUSD-150)

## **Manual testing steps**

N/A 

## **Screenshots/Recordings**

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

### **Before**

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

<!-- [screenshots/recordings] -->
N/A 
## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes the UI routing/layout decision for confirmations based on
navigation params, which could alter how confirmations render if params
are set incorrectly; coverage is updated to reduce regression risk.
> 
> **Overview**
> Adds an optional `forceBottomSheet` route param (`ConfirmationParams`)
and updates `useFullScreenConfirmation` to always return `false` when
it’s set, overriding the existing full-screen decision logic.
> 
> Updates confirmation-related unit tests to mock `useRoute`/`useParams`
and adds coverage ensuring `forceBottomSheet` disables full-screen
confirmations; also adjusts component tests that depend on
`useFullScreenConfirmation` by mocking it explicitly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
57f0b26. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

During account switches, network changes, or app backgrounding, the
Perps WebSocket connection is intentionally torn down via `clearAll()`.
This causes pending subscription operations (subscribe/unsubscribe) to
reject with `WebSocketRequestError` from the HyperLiquid SDK — which is
expected behavior.

However, 25 out of 30 error handlers in `HyperLiquidSubscriptionService`
were unconditionally calling `Logger.error()`, sending these expected
cleanup errors to Sentry. Only 5 handlers checked the `#isClearing` flag
before logging.

This PR:
- Adds a `#logErrorUnlessClearing()` private helper that checks the
`#isClearing` flag before forwarding to `Logger.error()` (Sentry)
- Routes all 30 error handlers through this helper (previously only 5
were guarded)
- Removes redundant inline `if (!this.#isClearing)` checks that are now
handled by the helper
- Imports `PerpsLogger` type for proper parameter typing

**Net effect**: During intentional disconnects, `WebSocketRequestError`
errors from pending subscription operations are suppressed from Sentry.
Genuine connection failures (when `#isClearing` is false) are still
reported.

## **Changelog**

CHANGELOG entry: Fixed: Suppressed expected WebSocket cleanup errors
from being reported to Sentry during intentional Perps disconnections

## **Related issues**

Fixes: Excessive `WebSocketRequestError: Failed to establish WebSocket
connection` errors on Sentry during account switches and reconnections

## **Manual testing steps**

```gherkin
Feature: Perps WebSocket error suppression during cleanup

  Scenario: user switches accounts while on Perps tab
    Given the user is on the Perps tab with an active WebSocket connection

    When user switches to a different account
    Then the Perps connection reconnects successfully
    And no WebSocketRequestError errors are logged to Sentry during the transition

  Scenario: user navigates away from Perps and returns
    Given the user is on the Perps tab with an active WebSocket connection

    When user navigates to the Wallet tab and back to Perps
    Then the connection is re-established without Sentry error noise
```

## **Screenshots/Recordings**

N/A — No UI changes. This is an internal error logging improvement.

### **Before**

Expected `WebSocketRequestError` errors during cleanup were sent to
Sentry (25 out of 30 error handlers were unguarded).

### **After**

All 30 error handlers now check `#isClearing` via the
`#logErrorUnlessClearing()` helper — expected errors during intentional
disconnect are suppressed.

## **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**
> Logging-only refactor gated by an existing `#isClearing` flag; primary
risk is accidentally suppressing real errors if `#isClearing` is set
unexpectedly.
> 
> **Overview**
> Reduces Sentry noise in `HyperLiquidSubscriptionService` by adding a
`#logErrorUnlessClearing()` helper that skips `logger.error` while
`#isClearing` is true (set during `clearAll()` intentional disconnects).
> 
> Routes all subscription setup/teardown `catch` paths
(subscribe/unsubscribe callbacks, feature-flag updates, and cleanup
flows) through this helper and removes the remaining inline `if
(!#isClearing)` guards; also imports `PerpsLogger` to type the helper’s
context parameter.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
315a553. 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 adds the Market Insights feedback collection flow, it introduces
the thumbs down feedback bottom sheet with reason selection and the
thumbsup as an immediate success action. It also wires analytics so
feedback submissions track Market Insights Interaction.

<img height="800" alt="Simulator Screenshot - iPhone 16e - 2026-02-24 at
12 12 34"
src="https://github.com/user-attachments/assets/84bfd91c-ea16-4902-b4fd-5f01e065307f"
/>
<img height="800" alt="Simulator Screenshot - iPhone 16e - 2026-02-24 at
12 12 45"
src="https://github.com/user-attachments/assets/6397879e-f7ba-46fd-8cbf-f8424b2e8bb5"
/>
<img height="800" alt="Simulator Screenshot - iPhone 16e - 2026-02-24 at
12 13 04"
src="https://github.com/user-attachments/assets/e061de88-a250-43ad-81cb-9e6f5f31ea33"
/>


## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Moderate UI/UX and analytics payload changes in a user-facing screen,
plus new bottom-sheet/toast wiring that could affect event shape and
feedback/sources interactions if misconfigured.
> 
> **Overview**
> Adds a *thumbs-down feedback flow* to Market Insights: tapping
thumbs-down now opens a new `MarketInsightsFeedbackBottomSheet` to
select a reason (optionally with free-text for “something else”), and
both thumbs-up and successful submission show a “Feedback submitted”
toast.
> 
> Refactors the sources UI so the `MarketInsightsSourcesFooter` no
longer owns the sources bottom sheet; instead it exposes
`onSourcesPress` and `MarketInsightsView` controls both the new sources
sheet and feedback sheet visibility, while extending interaction
analytics to include `feedback_reason`/`feedback_text` and keeping
source clicks tracked.
> 
> Updates test IDs, adds new unit tests for the feedback sheet, adjusts
existing view/footer tests, and adds new i18n strings including a fixed
footer disclaimer line.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fee510d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Xavier Brochard <xavier.brochard@consensys.net>
…26533)

## **Description**

When a user selects a custom token to pay with on the PerpsOrderView
(coming from Token Details), after tapping Long:
- User lands briefly on Token Details (wrong)
- Then gets redirected to Market Details
The expected behavior (which works when Perps balance is selected) is to
go directly to Market Details.
## **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: Redirects user to Market details page instead of token
details page after submitting a perps position when coming from token
details page

## **Related issues**

Fixes: #26482

## **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/1de2360a-cdd1-4750-a8e4-72f1a6f11a01


### **After**

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



https://github.com/user-attachments/assets/d19cafab-3ecd-465b-8540-c298dc3a0929




## **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**
> Small, localized change to navigation behavior gated by a new
`fromTokenDetails` param; primary risk is unintended back-stack/reset
behavior in this specific flow.
> 
> **Overview**
> Fixes the Token Details → Perps one-click trade flow by threading a
`fromTokenDetails` flag through `usePerpsActions` → `PerpsOrderRedirect`
→ confirmations.
> 
> When a deposit is confirmed in `PerpsOrderView` (custom pay token
path), the navigation now **resets directly to `PerpsMarketDetails`**
instead of `goBack()`, preventing the brief, incorrect return to Token
Details; the new flag is added to the Perps navigation param types and
passed through unchanged alongside the existing A/B test param.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
acea888. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
#26487)

<!--
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 the change:**
The `OnboardingSuccess` component was using the `useRoute()` hook
internally to access route parameters. This approach has several
drawbacks:
- Tightly couples the component to the navigation context
- Makes type derivation less explicit (required unsafe type assertion:
`route.params as { successFlow: ONBOARDING_SUCCESS_FLOW }`)
- Reduces testability as tests needed to mock the `useRoute` hook
globally

**Improvement/Solution:**
- Refactored `OnboardingSuccess` to receive `route` as a prop instead of
calling `useRoute()` internally
- Added proper TypeScript interfaces: `OnboardingSuccessRouteParams`,
`OnboardingSuccessParamList`, and `OnboardingSuccessScreenProps`
- Added a safe default value (`ONBOARDING_SUCCESS_FLOW.BACKED_UP_SRP`)
when route params are undefined using nullish coalescing
- Updated tests to pass the `route` prop directly instead of mocking
`useRoute`
- Added new test cases to cover edge cases (undefined params, undefined
successFlow)

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: N/A (internal refactoring)

## **Manual testing steps**

```gherkin
Feature: Onboarding Success Screen

  Scenario: User completes wallet creation with backed up SRP
    Given the user has completed creating a new wallet
    And the user has backed up their Secret Recovery Phrase

    When user reaches the onboarding success screen
    Then user should see "Your wallet is ready!" message
    And user should see the Done button
    And user should see "Manage default settings" link

  Scenario: User completes wallet import from seed phrase
    Given the user has imported their wallet using a seed phrase

    When user reaches the onboarding success screen
    Then user should see "Your wallet is ready!" message
    And user should see the Done button

  Scenario: User taps Done button
    Given the user is on the onboarding success screen

    When user taps the Done button
    Then user should be navigated to the home screen
```

## **Screenshots/Recordings**

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

### **Before**

N/A - No visual changes

### **After**

N/A - No visual 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.
## **Description**

Phase 3 analytics migration (Batch 3-3): migrate core services' utility
and middleware files from `MetaMetrics.getInstance()` to the new
analytics system.

**Reason**: Deprecate MetaMetrics in favour of the shared analytics
utility and AnalyticsController.

**Changes**: 7 source files (`SnapsMethodMiddleware`,
`trackSnapAccountEvent`, `logs/index`, `signatureUtils`,
`vaultCorruptionTracking`, `TrendingFeedSessionManager`) now use
`analytics.trackEvent()` and `AnalyticsEventBuilder` from
`app/util/analytics`; 4 test files updated to mock the analytics utility
instead of MetaMetrics.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MCWP-301 (Batch
3-3)

## **Manual testing steps**

```gherkin
Feature: Core Services analytics

  Scenario: user triggers a core services flow event
    Given app is open and user is in a core services flow

    When user performs an action that triggers analytics (e.g. signature approval, snap account event, trending feed session)
    Then the event is tracked on Mixpanel
```

## **Screenshots/Recordings**

N/A – analytics migration, no UI 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**
> Touches multiple core flows (Snaps middleware, signature
confirmations, trending feed sessions, vault corruption tracking, and
state-log export) by swapping analytics plumbing; risk is mainly
missing/changed event payloads or opt-in gating differences affecting
telemetry.
> 
> **Overview**
> Migrates several core-platform emitters off
`MetaMetrics.getInstance()`/`MetricsEventBuilder` to the shared
`analytics.trackEvent()` + `AnalyticsEventBuilder`, including Trending
feed session tracking, Snap account tracking, Snaps RPC middleware event
tracking (now via exported `trackSnapEvent`), signature confirmation
events, and vault-corruption detection.
> 
> Updates state-log export to source the ID from `analytics`
(`getAnalyticsId()` gated by `analytics.isEnabled()`) instead of
MetaMetrics, and refreshes/extends unit tests to mock the new analytics
modules (including new tests for `SnapsMethodMiddleware.trackSnapEvent`
and `handleSignatureAction`, plus adjusted vault-corruption and
trending-session tests).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
eb5a5a9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Maarten Zuidhoorn <maarten@zuidhoorn.com>
## **Description**

The Predict withdraw completion toast was hardcoded to display "USDC" as
the token symbol. This PR makes the toast dynamically resolve the actual
withdrawn token and amount from the transaction metadata stored
on-chain.

For post-quote withdrawals, the toast now uses `targetFiat` from the
transaction's `metamaskPay` metadata (reflecting the actual received
value after fees). The token symbol is resolved via
`selectSingleTokenByAddressAndChainId`, falling back to the chain's
native ticker via `selectTickerByChainId`.

The hardcoded `withdraw_completed_subtitle` i18n key (with "USDC") is
replaced by `withdraw_any_token_completed_subtitle` which accepts a
`{{token}}` placeholder. The old key is removed from all 15 locale
files.

## **Changelog**

CHANGELOG entry: Updated Predict withdraw toast to show the actual token
symbol and amount instead of hardcoded USDC

## **Related issues**

Fixes: MetaMask/MetaMask-planning#6986

## **Manual testing steps**

```gherkin
Feature: Predict withdraw toast shows correct token

  Scenario: user completes a post-quote withdraw of a non-USDC token
    Given user has a Predict position and initiates a withdrawal of USDT on BSC

    When the withdrawal transaction confirms
    Then the toast displays the fiat amount and "USDT" (not "USDC")

  Scenario: user completes a standard USDC withdraw
    Given user has a Predict position and initiates a USDC withdrawal

    When the withdrawal transaction confirms
    Then the toast displays the correct amount and "USDC"
```

## **Screenshots/Recordings**

### **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 user-facing messaging for withdraw confirmations and
introduces synchronous store reads + selector lookups, which could
produce incorrect amounts/symbols if metadata is missing or malformed,
though logic includes explicit fallbacks.
> 
> **Overview**
> Predict withdraw **success** toasts now optionally render a
*post-quote* message that shows the resolved token symbol and amount,
derived from the transaction’s `metamaskPay` metadata (via
`store.getState()` + `selectTransactionMetadataById`), rather than being
hardcoded to USDC.
> 
> Adds `getWithdrawConfirmedMessage` with fallbacks
(non-post-quote/invalid `targetFiat`/missing token -> existing amount
behavior and defaulting token to chain ticker or `USDC`), introduces a
new i18n string
`predict.withdraw.withdraw_any_token_completed_subtitle`, and extends
the hook unit tests to cover these cases with mocked selectors/store.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a2a4237. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Signed-off-by: dan437 <80175477+dan437@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**

This PR aligns the **Security and privacy** (SecuritySettings) and
**Change password** (ResetPassword) screens with the inline header
pattern by replacing their stack navbars with inline
`HeaderCompactStandard` and wrapping each screen in `SafeAreaView` from
`react-native-safe-area-context`.

**Reason for change:** Both screens previously used
`getNavigationOptionsTitle` and `navigation.setOptions()` (in
`useEffect` / `componentDidMount`) to configure the stack header.
Migrating to inline headers matches the app-wide header approach (see
`docs/header-alignment-plans.md`) and keeps these Settings subpages
consistent with others that already use `HeaderCompactStandard` (e.g.
General Settings, App Information).

**What changed:**

1. **MainNavigator** – `SecuritySettings` and `ResetPassword` now use
`options={{ headerShown: false }}` so the stack header is hidden and the
header is fully inline.
2. **SecuritySettings** – Root is `SafeAreaView` (from
`react-native-safe-area-context`) with `edges={{ bottom: 'additive' }}`,
followed by inline `HeaderCompactStandard` (title "Security and
privacy", `onBack` → `navigation.goBack()`, `includesTopInset`) and the
existing `ScrollView` content. Removed `getNavigationOptionsTitle` and
all `updateNavBar` logic. Styles: `wrapper` is flex + background for the
safe area container; new `content` style holds padding for the scroll
area.
3. **ResetPassword** – Root is `SafeAreaView` from
`react-native-safe-area-context` with `edges={{ bottom: 'additive' }}`,
followed by inline `HeaderCompactStandard` (title "Change password",
`onBack` → `navigation.goBack()`, `includesTopInset`) and the existing
`ScrollView`. Removed `getNavigationOptionsTitle`, `updateNavBar`, and
the `componentDidUpdate` that hid the back button while loading.
Replaced the inner `SafeAreaView` in `renderResetPassword()` with `View`
to avoid double safe area.
4. **Tests** – SecuritySettings: added "renders inline header with
Security and privacy title" and "calls navigation.goBack when header
back button is pressed". ResetPassword: added "renders inline header
with Change password title" and "calls navigation.goBack when header
back button is pressed". Updated snapshots for both.

User-visible behavior (titles, back navigation, safe areas) is
unchanged; the headers are now rendered inline.

## **Changelog**

This PR is not end-user-facing (internal header implementation; same
UI/UX, headers are now inline).

CHANGELOG entry: null

## **Related issues**

Fixes:
https://consensyssoftware.atlassian.net/jira/software/c/projects/DSYS/boards/1888?assignee=62afb43d33a882e2be47c36f&selectedIssue=DSYS-356

## **Manual testing steps**

```gherkin
Feature: Security and privacy / Change password inline headers

  Scenario: user opens Security and privacy from Settings
    Given the app is open and the user is on the main Settings screen

    When the user taps "Security and privacy"
    Then the Security and privacy screen is shown with an inline header "Security and privacy" and a back arrow on the left

    When the user taps the back arrow
    Then the app navigates back to the main Settings screen

  Scenario: user opens Change password and uses inline header
    Given the user is on the Security and privacy screen

    When the user taps "Change password"
    Then the Change password screen is shown with an inline header "Change password" and a back arrow on the left

    When the user taps the back arrow
    Then the app navigates back to the Security and privacy screen

  Scenario: safe area and content layout
    Given the user is on either Security and privacy or Change password

    When the screen is displayed
    Then the header sits below the status bar (safe area respected)
    And the page content is visible and not covered by the header
```

## **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/af39a638-cfb0-4d84-8c08-d14d1edc15fb

## **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**
> UI/header refactor limited to two settings screens plus snapshot/test
updates; minimal behavioral risk aside from potential safe-area/layout
regressions across devices.
> 
> **Overview**
> Refactors the **Security and privacy** and **Change password**
settings flows to use an inline `HeaderCompactStandard` and
`SafeAreaView` from `react-native-safe-area-context`, removing the old
stack-header configuration (`getNavigationOptionsTitle` /
`navigation.setOptions`).
> 
> Updates `MainNavigator` to hide the stack headers for
`SecuritySettings` and `ResetPassword`, adjusts `SecuritySettings`
layout/styles to separate safe-area wrapper vs scroll content, and
updates tests/snapshots (including new coverage for header title
rendering and back-button `goBack`, with back disabled during loading on
ResetPassword).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
546ea82. 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 updates the **Backup and Sync Settings** screen to use an inline
`HeaderCompactStandard` instead of stack navbar options.

**Reason for change:** Align Settings subpages with the app’s header
pattern: simple back + title screens should use `HeaderCompactStandard`
(or equivalent) rendered inline, with the stack header hidden, for
consistent layout and safe area handling.

**What changed:**

1. **MainNavigator.js** – For the `BackupAndSyncSettings` screen,
replaced `options={BackupAndSyncSettings.navigationOptions}` with
`options={{ headerShown: false }}` so the stack header is hidden and the
screen controls its own header.
2. **BackupAndSyncSettings.tsx** – Removed navbar-based header: dropped
`getNavigationOptionsTitle` import and the `useEffect` that called
`navigation.setOptions`; removed the static
`BackupAndSyncSettings.navigationOptions` (custom `headerLeft` with
`ButtonIcon`); removed `useParams` for `isFullScreenModal`. Wrapped the
screen in `SafeAreaView` (edges: bottom) and added inline
`HeaderCompactStandard` at the top with
`title={strings('backupAndSync.title')}`, `onBack={handleBack}`,
`includesTopInset`, and testIDs from the new testIds file. Scroll
content remains in `ScrollView` below the header.
3. **BackupAndSyncSettings.styles.ts** – Removed the exported `styles`
object containing `headerLeft` (no longer used).
4. **BackupAndSyncSettings.testIds.ts** – New file with
`BackupAndSyncSettingsSelectorsIDs`: `SAFE_AREA`, `HEADER`,
`BACK_BUTTON` for tests and component usage.
5. **BackupAndSyncSettings.test.tsx** – Navigation mock now provides
`goBack: mockGoBack` instead of `setOptions`; removed `navUtils` mock
(useParams, useRoute, etc.). Added tests: "wraps content in
SafeAreaView", "renders HeaderCompactStandard with backup and sync
title", "navigates back when back button is pressed". Snapshot updated
for SafeAreaView + inline header output.

## **Changelog**

This PR is not end-user-facing (header presentation aligned with design;
same screen content and behavior).

CHANGELOG entry: null

## **Related issues**

Fixes:
https://consensyssoftware.atlassian.net/issues?jql=issueKey%20in%20(DSYS-357%2CDSYS-358)&selectedIssue=DSYS-358

## **Manual testing steps**

```gherkin
Feature: Backup and Sync Settings header

  Scenario: user sees inline header on Backup and Sync Settings
    Given the app is open and the user is in Settings
    When the user navigates to Backup and Sync
    Then the Backup and Sync Settings screen shows an inline header with title "Backup and sync" and a back button
    And the stack navigator header is not visible

  Scenario: user can go back from Backup and Sync Settings
    Given the user is on the Backup and Sync Settings screen
    When the user taps the back button in the header
    Then the app navigates back to the previous Settings screen
```

## **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/1ec7a132-ea99-4094-a3b9-cc002b6ffae4


<!-- [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**
> UI-only navigation/header refactor for a single settings screen;
minimal behavioral change beyond back navigation wiring and
safe-area/layout differences.
> 
> **Overview**
> Moves the `Backup and Sync` settings screen off stack-provided navbar
options and onto an **inline** `HeaderCompactStandard`, while hiding the
stack header (`headerShown: false`) for that route.
> 
> Wraps the screen in a `SafeAreaView` (with bottom additive inset) and
introduces new testIDs and unit tests to assert safe-area wrapping,
header title rendering, and back-button behavior; removes now-unused
header-left styling and navigation-options code, and updates snapshots
accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
47a8b0a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…26462)

## **Description**

Adds a dedicated Order Details screen for
`FIAT_ORDER_PROVIDERS.RAMPS_V2` orders, which previously were
incorrectly routed to the Aggregator order details screen (which expects
a different data shape). This PR also fixes a related analytics bug
where RAMPS_V2 orders were being processed by
`getAggregatorAnalyticsPayload` instead of a dedicated handler.

**What changed:**
- New `RampsOrderDetails` screen (`Ramp/Views/OrderDetails`) with
loading, processing, completed, failed, and cancelled states
- New `ProcessingInfoModal` bottom sheet explaining card processing
times, with a deep link to the provider's support page (opens via
InAppBrowser)
- New `getRampsOrderDetailsNavbarOptions` for the dedicated navbar (not
reusing Aggregator/Deposit navbar options)
- `getOrderAmount` utility moved to `Ramp/utils` (shared level) —
Aggregator re-exports from there
- `OrdersList` now routes RAMPS_V2 orders to the new screen instead of
the Aggregator details screen
- External links ("View on provider", "Contact support") open in-app via
`react-native-inappbrowser-reborn` with `SimpleWebview` fallback
- `showCloseButton` prop: the close button only appears when navigating
from the checkout flow, not from order history
- Network badge uses `cryptoCurrency.chainId` (CAIP-2 format) to support
EVM, BTC, Solana, and non-EVM chains
- New `ramps_order_details` localization namespace with dedicated
strings
- New `Routes.RAMP.RAMPS_ORDER_DETAILS` and
`Routes.RAMP.MODALS.PROCESSING_INFO` registered in `MainNavigator`

**Analytics fix (included):**
- New `getRampsV2AnalyticsPayload` builder for RAMPS_V2 orders
- `getOrderAnalyticsPayload` now correctly routes RAMPS_V2 orders to the
dedicated handler

## **Changelog**

CHANGELOG entry: Added a dedicated order details screen for Ramps V2
(Unified Buy) orders with status tracking, provider link, and processing
info modal

## **Related issues**

Refs: #feat/unified-order-processor

## **Manual testing steps**

```gherkin
Feature: Ramps V2 order details screen

  Scenario: user views a pending Ramps V2 order from order history
    Given the user has a pending RAMPS_V2 order in their order history
    When the user taps the order in the order list
    Then the Ramps order details screen opens (not the aggregator one)
    And the screen shows a loading/processing state with skeleton loaders
    And there is no close button

  Scenario: user views a completed Ramps V2 order from order history
    Given the user has a completed RAMPS_V2 order
    When the user taps it in order history
    Then the details screen shows the crypto amount, fiat total, fees, order ID, and date
    And the status shows "Complete" in green
    And tapping "View on <provider>" opens the provider link inside the app
    And tapping the order ID copies it to clipboard

  Scenario: user taps the info icon next to "Card purchases"
    Given the user is on the Ramps order details screen
    When the user taps the info icon next to "Card purchases typically take a few minutes"
    Then a bottom sheet modal appears explaining card processing
    And tapping "Go to <provider> support" opens the support URL inside the app

  Scenario: network badge displays correctly for non-EVM chains
    Given the user has a RAMPS_V2 order on a Solana or BTC network
    When the user views the order details
    Then the network badge shows the correct network icon using the CAIP-2 chainId
```

## **Screenshots/Recordings**

<!-- Add before/after screenshots showing the new order details screen
vs. the aggregator one -->

### **Before**
RAMPS_V2 orders routed to Aggregator order details screen (wrong data
shape, potential crash)

### **After**
Dedicated Ramps order details screen with correct data handling for all
states

Aggregator Order:


https://github.com/user-attachments/assets/cdf73b86-bb59-4403-8dbd-52827fe91e2f


Native Order:


https://github.com/user-attachments/assets/0f3fd6da-be76-48b8-b29b-363ac2ba3f80



## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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 ramp navigation, order ID/network mapping, and analytics
payload selection; regressions could mis-route users or break order
refresh/analytics for deposit/RAMPS_V2 orders.
> 
> **Overview**
> Adds a **dedicated order-details flow for
`FIAT_ORDER_PROVIDERS.RAMPS_V2`** by introducing
`Routes.RAMP.RAMPS_ORDER_DETAILS` (plus standalone
`BANK_DETAILS_STANDALONE`) and wiring navigation so RAMPS_V2 orders no
longer route through aggregator/deposit details screens. The new UI
includes `OrderContent` (copy order id, provider deep link, network
badge normalization, optional bank-transfer details + “Manage bank
transfer”), periodic refresh/polling, and a `showCloseButton` path used
when coming from checkout.
> 
> Introduces a new bottom-sheet `ProcessingInfoModal` (registered under
`Routes.RAMP.MODALS.PROCESSING_INFO`) and switches support/provider
links to open via `react-native-inappbrowser-reborn` with
`SimpleWebview` fallback. Also fixes order processing/analytics
correctness by (1) adding `getRampsV2AnalyticsPayload` and routing
RAMPS_V2 through it, (2) preferring `providerOrderId` as the stored
`FiatOrder.id` for RAMPS_V2 and Deposit while preserving the original
redux id during refresh, and (3) preferring `cryptoCurrency.chainId` for
unified-order network plus adding `amountInUSD`/`currencySymbol`
mapping; includes updated/new tests and i18n strings
(`ramps_order_details`).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
99dd34f. 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 updates the **Buy & sell crypto (Ramp) Settings** and
**Activation Key Form** screens to use inline `HeaderCompactStandard`
instead of stack navbar options.

**Reason for change:** Align Settings-related Ramp screens with the
app’s header pattern: simple back + title screens should use
`HeaderCompactStandard` (or equivalent) rendered inline, with the stack
header hidden, for consistent layout and safe area handling.

**What changed:**

1. **MainNavigator.js** – For `Routes.RAMP.SETTINGS` (RampSettings) and
`Routes.RAMP.ACTIVATION_KEY_FORM` (RampActivationKeyForm), added
`options={{ headerShown: false }}` so both screens control their own
headers.
2. **Ramp Aggregator Settings (Settings.tsx)** – Removed `useEffect` and
`getNavigationOptionsTitle`; removed `useAppTheme`. Wrapped the screen
in `SafeAreaView` (edges: top) and added inline `HeaderCompactStandard`
with `title={strings('app_settings.fiat_on_ramp.title')}` (“Buy & sell
crypto”), `onBack={handleBack}`, and exported
`RAMP_SETTINGS_HEADER_TEST_ID`. Content remains in
`KeyboardAvoidingView` > `ScreenLayout` below the header.
3. **Activation Key Form (ActivationKeyForm.tsx)** – Removed `useEffect`
and `getNavigationOptionsTitle`; removed `useTheme`. Wrapped the screen
in `SafeAreaView` (edges: top) and added inline `HeaderCompactStandard`
with dynamic title (Add vs Edit activation key), `onBack={handleBack}`,
and exported `ACTIVATION_KEY_FORM_HEADER_TEST_ID`. Content remains in
`ScreenLayout` below the header.
4. **Settings.test.tsx** – Navigation mock now provides `goBack:
mockGoBack` instead of `setOptions`. Added tests: “renders inline header
with title Buy & sell crypto” and “navigates back when header back
button is pressed” (using `RAMP_SETTINGS_HEADER_TEST_ID` and back button
within header).
5. **ActivationKeyForm.test.tsx** – Removed `setOptions` from navigation
mock; introduced `mockUseParamsValue` for `useParams` to drive Add vs
Edit titles. Added tests: “renders inline header with title Add
activation key”, “renders inline header with title Edit activation key
when key param is provided”, “navigates back when header back button is
pressed”. Snapshots updated for both components.

## **Changelog**

This PR is not end-user-facing (header presentation aligned with design;
same screen content and behavior).

CHANGELOG entry: null

## **Related issues**

Fixes:
https://consensyssoftware.atlassian.net/issues?jql=issueKey%20in%20(DSYS-357%2CDSYS-358%2CDSYS-359)&selectedIssue=DSYS-359

## **Manual testing steps**

```gherkin
Feature: Buy & sell / Activation Key header

  Scenario: user sees inline header on Buy & sell crypto Settings
    Given the app is open and the user is in Settings
    When the user opens Buy & sell crypto (Ramp) settings
    Then the screen shows an inline header with title "Buy & sell crypto" and a back button
    And the stack navigator header is not visible

  Scenario: user sees inline header on Activation Key form (Add)
    Given the user is on Buy & sell crypto Settings (internal build)
    When the user taps to add an activation key
    Then the Activation Key form shows an inline header with title "Add activation key" and a back button

  Scenario: user sees inline header on Activation Key form (Edit)
    Given the user is editing an existing activation key
    Then the form shows an inline header with title "Edit activation key" and a back button

  Scenario: user can go back from Ramp screens
    Given the user is on Buy & sell crypto Settings or Activation Key form
    When the user taps the back button in the header
    Then the app navigates back to the previous screen
```

## **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/331b0443-b5fa-4f66-afe8-96bb22be64da

## **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**
> UI-only refactor of header rendering and related tests; no changes to
Ramp business logic or data flow, with minimal risk limited to
navigation/visual regressions on these two screens.
> 
> **Overview**
> Updates the Ramp `Settings` and `ActivationKeyForm` screens to **hide
the stack header** and instead render an inline `HeaderCompactStandard`
wrapped in a top `SafeAreaView`, providing consistent title/back
behavior and safe-area handling.
> 
> Refactors navigation-title logic by removing
`navigation.setOptions`/theme dependencies, adds explicit header/back
`testID`s, and expands unit tests (plus snapshot updates) to assert
header titles (Add vs Edit) and back navigation via `goBack`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fe81980. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Phase 3 analytics migration (Batch 3-12): migrate Wallet views
(`WalletActions`, `Wallet/index`, `TradeWalletActions`) from
`useMetrics` to the new `useAnalytics` hook.

**Reason**: Deprecate MetaMetrics in favour of the shared analytics
utility and AnalyticsController.

**Changes**: `WalletActions.tsx`, `Wallet/index.tsx`, and
`TradeWalletActions.tsx` now use `useAnalytics` from
`app/components/hooks/useAnalytics/useAnalytics` instead of
`useMetrics`; `MetaMetricsEvents` is imported from `app/core/Analytics`;
embedded event properties for `WALLET_TOKENS` and `WALLET_COLLECTIBLES`
are explicitly passed via `.addProperties()`.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MCWP-302 (Batch
3-12)

## **Manual testing steps**

```gherkin
Feature: Wallet analytics

  Scenario: user triggers a wallet flow event
    Given app is open and user is in the wallet home screen

    When user performs an action that triggers analytics (e.g. switch tab to Tokens/Collectibles, tap network selector, tap Earn button)
    Then the event is tracked on Mixpanel
```

## **Screenshots/Recordings**

N/A – analytics migration, no UI 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]
> **Low Risk**
> Primarily a hook swap for analytics wiring plus small event-payload
changes; no user-facing behavior or core transaction logic is modified,
but event schemas/volume could change if properties are mis-specified.
> 
> **Overview**
> Migrates wallet action surfaces (`WalletActions`,
`TradeWalletActions`, and `Wallet/index`) from the legacy `useMetrics`
hook to the shared `useAnalytics` hook and sources `MetaMetricsEvents`
from `core/Analytics`.
> 
> As part of the migration, wallet tab-selection tracking is updated so
`WALLET_TOKENS` and `WALLET_COLLECTIBLES` events now include explicit
properties via `.addProperties()` (e.g., `action`/`name`), aligning
emitted payloads with the new analytics pipeline.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ea02ecd. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…s) (#26483)

## **Description**

This PR refactors the `App.tsx` navigator and `AccountStatus` component
to use the `route` prop passed from React Navigation instead of using
the `useRoute` hook directly. This enables proper TypeScript type
inference for route parameters at the component level.

**Motivation:**
- Using `useRoute` hook loses type information because the hook returns
a generic route type
- Passing `route` as a prop allows TypeScript to infer the correct
parameter types from the navigation stack definition

**Changes:**
- `App.tsx`: Updated navigation configuration to pass route props
- `AccountStatus`: Updated to receive `route` from props with proper
typing
- Added `types.ts` file for AccountStatus route parameter type
definitions

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: Part of #26183

## **Manual testing steps**

Feature: Account Status Screen

  Scenario: User views account status
    Given the user has an account
    When user navigates to Account Status screen
    Then the screen should load with correct account information
    And display status based on route parameters

Feature: App Navigation

  Scenario: Navigation passes route props correctly
    Given the app is running
    When user navigates between screens
    Then route props should be passed correctly to child components
    

## **Screenshots/Recordings**

### **Before**

N/A - Refactor only, no visual changes

### **After**

N/A - Refactor only, no visual 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]
> **Low Risk**
> Primarily a typing/prop-plumbing refactor in onboarding navigation and
`AccountStatus`, with minimal behavioral change aside from how params
are sourced/defaulted.
> 
> **Overview**
> Refactors `AccountStatus` to derive `type` and related values from the
React Navigation `route` prop (typed via a new `AccountStatusParams`
interface) instead of the `useRoute` hook/explicit `type` prop.
> 
> Updates the onboarding navigator to route
`AccountAlreadyExists`/`AccountNotFound` directly to `AccountStatus`
with `initialParams` (`type: 'found' | 'not_exist'`), and
adjusts/expands tests to pass mocked `route` props and cover
missing/undefined params defaults.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9297fb1. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@pull pull Bot locked and limited conversation to collaborators Feb 25, 2026
@pull pull Bot added the ⤵️ pull label Feb 25, 2026
@pull pull Bot merged commit d173b6e into Reality2byte:main Feb 25, 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.