Skip to content

release: 8.7.0 - #34442

Draft
metamask-ci[bot] wants to merge 240 commits into
stablefrom
release/8.7.0
Draft

release: 8.7.0#34442
metamask-ci[bot] wants to merge 240 commits into
stablefrom
release/8.7.0

Conversation

@metamask-ci

@metamask-ci metamask-ci Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🚀 v8.7.0 Testing & Release Quality Process

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


📋 Key Processes

Testing Strategy

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

GitHub Signoff

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

Issue Resolution

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

Cherry-Picking Criteria

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

🗓️ Timeline and Milestones

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

✅ Signoff Checklist

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

Team sign-off checklist

  • Accounts
  • Assets
  • BE Trade
  • Card
  • Confirmations
  • Core Platform
  • Design System
  • Earn
  • Engagement
  • MetaMask Delivery
  • Mobile Platform
  • Mobile UX
  • Money Movement
  • Networks
  • Onboarding
  • Perps
  • Predict
  • Product Safety
  • Social & AI
  • Swaps and Bridge
  • Transactions
  • Wallet Integrations

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

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

Many thanks in advance

Reference

ghgoodreau and others added 30 commits July 30, 2026 20:56
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

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

Polymarket actively covers additional soccer, baseball, hockey, and
American football leagues whose markets currently appear in the Predict
feed without the curated game-page experience. This change expands
`predictExtendedSportsMarkets` to include those leagues so supported
game events open with grouped markets.

The app-side sports capability list and slug parser now support the
eleven leagues that were not already recognized by the client, including
their provider-defined home/away ordering. The `predictLiveSports`
production test configuration is expanded for those leagues as well
because game construction and team loading are prerequisites for
extended market grouping.

Leagues added to `predictExtendedSportsMarkets`:

- Soccer: `uel`, `col`, `fl1`, `ere`, `bra`, `por`, `bel1`, `elc`, `lib`
- Baseball: `kbo`, `npb`, `cpbl`
- Hockey: `shl`, `khl`, `cehl`, `dehl`
- American football: `nfl`, `cfb`, `cfl`

NFL's standard game-line markets are supported by this change. NFL
player props such as touchdowns and yardage remain outside the flag's
enabled market types and are not part of this scope.

As a temporary compatibility guard, directly opened child events remain
on their existing generic details page whenever any active child market
cannot be represented by the currently enabled grouped market types.
Fully groupable children and parent game cards continue to use the
curated page. This guard can be removed once all relevant sports market
types are supported.

Legacy Predict Appium flows explicitly disable both the `7.82.0` and
`8.6.0` extended-sports variations through a shared helper. This
prevents deep-merged production defaults from unintentionally changing
cash-out, claim, geo-restriction, open-position, and withdrawal smoke
scenarios.

CFB, NFL, and NBA first-half moneyline markets are enabled under a
dedicated `First Half` group. New league and market-type configuration
is versioned at `8.6.0`; existing `7.79.0` and `7.82.0` payloads remain
unchanged for older clients.

Provider data note: two historical FL1 Nice/Saint-Etienne playoff events
use `nic` in the event slug while the embedded team and `/teams`
endpoint use `ogc` for OGC Nice. This has been isolated for confirmation
with Polymarket before adding a client-side alias.

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

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

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

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

CHANGELOG entry: Added curated Predict game pages for more soccer,
baseball, hockey, and football leagues

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes: https://consensyssoftware.atlassian.net/browse/PRED-1139

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Extended Predict sports market coverage

  Scenario Outline: user opens a newly enabled sports game
    Given predictLiveSports includes "<league>"
    And predictExtendedSportsMarkets includes "<league>"
    And Polymarket returns an active "<league>" game with game and team metadata

    When the user opens the game card from the Predict feed
    Then the curated game details page opens
    And supported markets are grouped by market type

    Examples:
      | league |
      | uel    |
      | col    |
      | fl1    |
      | ere    |
      | bra    |
      | por    |
      | bel1   |
      | elc    |
      | lib    |
      | kbo    |
      | npb    |
      | cpbl   |
      | shl    |
      | khl    |
      | cehl   |
      | dehl   |
      | nfl    |
      | cfb    |
      | cfl    |

  Scenario: user opens a previously enabled sports game
    Given the existing extended sports leagues remain enabled

    When the user opens an existing supported game card from the Predict feed
    Then the curated game details page opens
    And its supported markets remain grouped by market type

  Scenario: user directly opens a child event containing an ungroupable market
    Given the child event contains at least one active market type that is not enabled for grouping

    When the user opens that child event from search or a direct link
    Then the original child event opens on the generic market details page
    And its active markets remain accessible
```

Automated validation:

- Nine focused Predict and feature-flag suites covering provider
resolution, parsing, grouping, rendering, flags, league support, and
upstream esports integration (554 tests passed)
- Android Predict Appium smoke discovery (7 tests listed successfully)
- `yarn lint:tsc`
- Targeted ESLint and Prettier checks for all changed files

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

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

### **Before**

N/A. This change expands configuration and league parsing without
introducing a new static UI; several covered leagues are currently out
of season.

### **After**

N/A. The resulting game page uses the existing curated sports UI and
depends on active Polymarket events for each league.

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [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.

#### Performance checks (if applicable)

- [x] I've tested on Android
- N/A. This is a platform-independent feature flag and parsing change
with no Android-specific code.
- [x] I've tested with a power user scenario
- N/A. League parsing and market grouping do not depend on wallet size,
account count, or token count.
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- N/A. This change adds no new runtime operation or
performance-sensitive execution path.

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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 feature-flag defaults, league parsing, and Polymarket event
resolution paths that affect which details UI users see; scope is large
but covered by extensive unit tests and smoke flag isolation.
> 
> **Overview**
> Expands **Predict** curated sports game pages to many additional
leagues (soccer, baseball, hockey, American football) by extending
`PredictSportsLeague`, `SUPPORTED_SPORTS_LEAGUES`, `LEAGUE_SLUG_CONFIGS`
slug/tag parsing, and draw-capable league sets.
> 
> Adds **`8.6.0`** production defaults for `predictLiveSports` and
`predictExtendedSportsMarkets` (league lists plus richer
`enabledSportsMarketTypes`), while keeping older `7.79.0` / `7.82.0`
payloads unchanged.
> 
> Enables **`first_half_moneyline`** as a supported/grouped market type
(mapped to a **First Half** outcome group, separate from game lines) and
treats it as moneyline-like in sports constants.
> 
> Changes **Polymarket** market-details resolution: child events with a
parent are **not** merged into the parent when any **active** market
type is outside the enabled grouping set (`#canGroupAllActiveMarkets`),
so direct links keep the generic child page until all active markets are
groupable.
> 
> Centralizes **Appium** smoke disabling of extended sports via
`remoteFeatureFlagExtendedSportsMarketsDisabledForPredictSmoke` (both
`8.6.0` and `7.82.0` variations).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
c9c9fd3. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…s cp-8.6.0 (#34029)

## **Description**

Newly onboarded users saw the wallet-home onboarding checklist and the
Money card at the same time, giving them two competing primary CTAs. Per
the ticket (approved by Johann), the Money card is now hidden while the
checklist is on screen so the checklist owns the action.

The card is gated on the same selector the checklist tile already reads
— `selectShouldShowWalletHomeOnboardingSteps`, surfaced in this view as
the existing `inWalletHomePostOnboardingFlow` — so the two can't drift
apart. That also satisfies the second acceptance criterion for free:
dismissing or completing the checklist flips the selector, and the card
reappears in the same render as the balance row that
`AccountGroupBalance` swaps back in. No separate dismissal wiring was
needed.

Deliberately scoped to the card. The header's activity button keeps
using `isMoneyAccountVisible` and is unaffected — only the surface
underneath the checklist was in conflict. `MoneyBalanceCard` has a
single render site (`app/components/Views/Wallet/index.tsx`), so this is
a one-line gate plus the derived flag.

Side benefit: `MoneyBalanceCard` fires a "component viewed" analytics
event on mount, so it no longer reports views to users who never
actually see the card.

## **Changelog**

CHANGELOG entry: Hid the Money card on the wallet home screen while the
onboarding checklist is showing, so new users have a single clear next
step

## **Related issues**

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

## **Manual testing steps**

```gherkin
Feature: Money card visibility during wallet-home onboarding

  Scenario: newly onboarded user sees only the checklist
    Given the Money account flag is on and the user is geo-eligible
    And the user has just completed onboarding so the wallet-home checklist is showing

    When user views the wallet home screen
    Then the onboarding checklist is visible
    And the Money card is not rendered below it

  Scenario: user dismisses the checklist
    Given the wallet-home onboarding checklist is showing

    When user dismisses the checklist
    Then the account balance is shown
    And the Money card appears below it

  Scenario: user completes the checklist
    Given the user is on the last checklist step

    When user completes the flow
    Then the balance and the Money card both appear after the exit animation

  Scenario: existing user is unaffected
    Given the user is not eligible for the wallet-home checklist
    And the Money account flag is on and the user is geo-eligible

    When user views the wallet home screen
    Then the Money card is visible as before
```

## **Screenshots/Recordings**


https://github.com/user-attachments/assets/833ba151-9ad6-435d-9b56-efaf723f61e0

### **Before**

<img width="750px" alt="Simulator Screenshot - iPhone 17 Pro -
2026-07-29 at 20 45 37"
src="https://github.com/user-attachments/assets/0c683e00-533b-4bbe-89d4-ec6250b8bdc9"
/>

### **After**

<img width="750px" alt="Simulator Screenshot - iPhone 17 Pro -
2026-07-29 at 20 48 36"
src="https://github.com/user-attachments/assets/5556368f-a16e-4097-8c98-b27d4b820ea3"
/>

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

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Scoped UI visibility change on wallet home with no auth, payments, or
data-model changes; behavior is covered by new component-view tests.
> 
> **Overview**
> **Wallet home** no longer shows the **Money balance card** while the
post-onboarding checklist is active, so new users aren’t offered two
competing primary actions.
> 
> Rendering now uses a **`showMoneyBalanceCard`** flag: Money must be
enabled and geo-eligible, and the user must **not** be in the
wallet-home post-onboarding flow (`inWalletHomePostOnboardingFlow`, same
signal as the checklist). Dismissing or finishing the checklist flips
that flag and the card can mount again in the same render cycle as the
normal balance UI.
> 
> **Component-view tests** cover the card hidden with the checklist
visible, and visible again after skip on the last step.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
d8d1877. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…show Pay fees cp-8.6.0 (#34026)

## **Description**

Two defects on the Predict funding flow when the activity redesign is
enabled.

**1. "Track" opened the legacy details screen.** The funding toast's
Track button routed to `Routes.TRANSACTION_DETAILS` (the confirmations
team's screen) unconditionally. The activity list already sends that
same local row to the redesigned `Routes.ACTIVITY_DETAILS` when
`selectIsTransactionsRedesignEnabled` is on, so the toast was the only
entry point that disagreed — the same transaction rendered two different
ways depending on how you reached it.

`navigateToTransactionDetails` now accepts
`isTransactionsRedesignEnabled` + `chainId` and navigates to
`ACTIVITY_DETAILS` when both are present. The flag is passed in by the
caller rather than read from the store, so this util stays store-free
(it lives in `app/util`, where importing the store risks an import
cycle). Callers that don't pass the new options are unaffected, so the
Perps toast keeps its current destination.

**2. The redesigned funding details had no fee rows.** MetaMask Pay
records its already-aggregated fiat fees on the `TransactionMeta`
(`metamaskPay.networkFeeFiat` / `bridgeFeeFiat` / `totalFiat`). The
activity adapter's token-denominated `data.fees` is empty for these
rows, so the shared `ActivityDetailsFeesAndTotal` had nothing to render.

A new `ActivityDetailsPayFees` section reads `metamaskPay` and renders
Network fee / Bridge fee / Total using the redesign's own
`ActivityDetailRow` primitives, formatted as USD via `useFiatFormatter({
currency: 'usd' })` — the same source and currency the legacy rows use,
so the two screens can't disagree. A recorded zero still renders (a
sponsored network fee shows `$0`); absent values omit their row.

**Scope:** deposits only. Withdrawals relabel these rows ("Provider fee"
/ "Received total" off `targetFiat`) and have no redesigned copy in the
`activity_details` locale namespace yet — this matches the existing,
deliberately deposit-only step timeline in the same template. Broader
`mmPay` coverage (Perps and Money-account deposits/withdrawals) needs
adapter work, since `local-transaction.ts` only special-cases the
Predict types today; worth a follow-up ticket.

**Known limitation:** `metamaskPay` lives only on the local
`TransactionMeta`, which
`TransactionController#trimTransactionsForState` eventually trims. Once
trimmed, the row resolves from the indexed API copy and the fee section
renders nothing. It degrades to absent rather than wrong, and the legacy
screen is worse in the same situation (blank body, since
`useTransactionDetails` returns undefined). Pre-existing platform
constraint, not introduced here.

## **Changelog**

CHANGELOG entry: Fixed the Predictions "Add funds" activity details to
show network fee, bridge fee and total, and to open the redesigned
details screen from the funding notification

## **Related issues**

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

## **Manual testing steps**

```gherkin
Feature: Predict funding activity details

  Scenario: user tracks a Predictions deposit from the funding toast
    Given the activity redesign feature flags are enabled
    And the user has added funds to their Predictions account

    When user taps "Track" on the "Adding funds" toast
    Then the redesigned activity details screen opens
    And the screen shows Network fee, Bridge fee and Total rows
    And tapping back returns to the Predictions-filtered activity list

  Scenario: user opens the same deposit from the activity list
    Given the activity redesign feature flags are enabled

    When user opens Wallet then Activity
    And user taps the "Add funds" Predictions row
    Then the same redesigned details screen opens with identical fee values

  Scenario: fee values match the legacy screen
    Given the activity redesign feature flags are disabled

    When user taps "Track" on the "Adding funds" toast
    Then the legacy details screen opens
    And its Network fee, Bridge fee and Total match the redesigned screen
```

## **Screenshots/Recordings**


https://github.com/user-attachments/assets/22356882-4ca0-4176-8a47-50ff3d7b4cc4

### **Before**


https://github.com/user-attachments/assets/1ca0fc3e-7d5f-48b9-b272-0c37e243d6a4

### **After**


https://github.com/user-attachments/assets/22356882-4ca0-4176-8a47-50ff3d7b4cc4

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

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> UI and navigation changes behind an existing feature flag, with legacy
fallback when chain id is missing; fee display reads existing Pay
metadata without changing payment logic.
> 
> **Overview**
> Aligns Predict funding **Track** navigation with the activity redesign
and surfaces **MetaMask Pay** fee rows on the redesigned deposit details
screen.
> 
> **Track navigation:** `navigateToTransactionDetails` now accepts
`isTransactionsRedesignEnabled` and a CAIP-2 `chainId`. When both are
set, it opens `ACTIVITY_DETAILS` instead of legacy
`TRANSACTION_DETAILS`; without `chainId` it still falls back to legacy.
Predict deposit toasts pass the redesign flag and chain id from
transaction metadata (`toEvmCaipChainId`).
> 
> **Pay fees on redesigned details:** New `ActivityDetailsPayFees` reads
`metamaskPay` from local transaction meta and renders network fee,
bridge fee, and total in **USD** (even if the wallet display currency is
not USD), with token/network badges via extracted
`ActivityFeeTokenValue`. Deposit **Predict** funding template shows this
section above the step timeline when Pay fiat metadata exists; zero fees
still display (e.g. sponsored `$0`).
> 
> Tests cover navigation branches, Pay fee rendering edge cases, and
Predict details integration.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
92bc0dc. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

`PriceChart` was recomputing `prices.map(...)` into `priceList` on every
render. Chart scrubbing updates `positionX` continuously, so that map
over hundreds of points ran on every touch frame and also handed a fresh
array identity into the stablecoin Y-axis `useMemo`, defeating its
cache.

This wraps the derivation in `useMemo` keyed on `prices`, so scrub
re-renders reuse the same `priceList` and the downstream stablecoin
range memo stays valid. Upstream `prices` is already referentially
stable (`useState` in `useTokenHistoricalPrices`, and
`distributedPriceData` is memoized in `Price.legacy`).

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: ASSETS-3723
Refs: #31272

## **Manual testing steps**

N/A — behavior-preserving performance change. Existing `PriceChart` unit
tests cover empty/loading/stablecoin/scrub paths.

Optional smoke: open token overview → scrub chart across 1D/1W/1M →
confirm line, end-dot, and scrub tooltip still update correctly.

## **Screenshots/Recordings**

N/A — no UI/behavior change.

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

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

### Changed files

- `app/components/UI/AssetOverview/PriceChart/PriceChart.tsx` — memoize
`priceList` with `useMemo(..., [prices])`
- Verified: `npx eslint` (warnings only, pre-existing), `yarn prettier
--check`, `yarn jest --coverage=false PriceChart.test.tsx` (25/25),
`yarn lint:tsc`

<div><a
href="https://cursor.com/agents/bc-0ae13633-4418-407c-81fd-a66ccdbee10b"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/automations/ad0b477a-8482-11f1-a7d1-d6b4613131ce"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/view-automation-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/view-automation-light.png"><img
alt="View Automation" width="141" height="28"
src="https://cursor.com/assets/images/view-automation-dark.png"></picture></a>&nbsp;</div>

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Behavior-preserving React memoization in chart rendering only; no API,
auth, or data-handling changes.
> 
> **Overview**
> **PriceChart** no longer rebuilds `priceList` on every render. The
`prices → numeric series` map is wrapped in `useMemo` with `[prices]` as
the dependency.
> 
> Chart scrubbing updates `positionX` on each touch frame, which
previously re-ran that map over the full series and passed a new array
into the stablecoin Y-axis `useMemo`, forcing extra sort/range work
during gestures. When `prices` is unchanged, scrub re-renders now reuse
the same `priceList` reference and keep that downstream memo valid. **No
chart behavior or UI change**—render-path optimization only.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
a1febd4. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: prithpal.sooriya <prithpal.sooriya@consensys.net>
)

## **Description**

<!-- mms-check: type=text required=true -->

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

This continues work on the Perps Pro market detail screen, adding a new
account balance bottom sheet and polishing several existing pieces of
the header, order form, order book, and positions panel so they line up
with Figma.

- **Account balance bottom sheet**: tapping the wallet icon in the Pro
header now opens a `PerpsBalanceBottomSheet` showing total balance,
available balance, and unrealized P&L, with quick access to Withdraw /
Add funds and Perps activity — without leaving the market screen.
- **Header polish**: the market identity/price row now crossfades into a
compact `[Ticker]-[collateral] perp` subtitle vs. a live price display
as the user scrolls, and `PerpsMarketIdentity` was adjusted to match.
- **Order book & chart collapse animation**: the order-book column and
the chart panel now animate in/out (fade + layout transition) when
collapsed/expanded instead of abruptly mounting/unmounting.
- **Pro order form slider**: the design system `Slider` has no
small/compact size variant, so the "Size (USD)" slider in the Pro order
form is now visually shrunk (via a scale-transform wrapper) to match
Figma's small slider spec, while preserving its full touch target. Also
added the top spacing above the slider and made the "Size (USD)" label
tappable to focus the input and open the keyboard, both to match Figma.
- Misc smaller polish to `PerpsProOrderCard`, `PerpsProPositionsPanel`,
`PerpsProUnrealizedPnl`, and `LivePriceHeader`.

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

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

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

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

CHANGELOG entry: Added an account balance bottom sheet to the Perps Pro
market screen and polished its header, order form, and order book/chart
animations

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes:

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Perps Pro market view polish

  Background:
    Given I am logged into MetaMask Mobile
    And I have opened a Perps Pro market detail screen

  Scenario: user opens the account balance bottom sheet from the header
    When user taps the wallet icon in the Pro market header
    Then a bottom sheet should open showing total balance, available balance, and unrealized P&L
    And the sheet should offer Withdraw and Add funds actions
    And tapping outside the sheet should close it without leaving the market screen

  Scenario: header subtitle crossfades into the live price on scroll
    Given the market screen is scrolled to the top, showing the price section
    When user scrolls down past the price section
    Then the header should crossfade from the "[Ticker]-[collateral] perp" subtitle to a compact live price with 24h change
    When user scrolls back to the top
    Then the header should crossfade back to the subtitle

  Scenario: order book and chart collapse/expand with animation
    Given the order book column and chart panel are both expanded
    When user collapses the order book
    Then the order book column should fade/animate out and the order form should smoothly resize to fill the row
    When user expands the order book again
    Then it should fade/animate back in

    When user collapses the chart panel
    Then the chart should animate out and the panels below it should slide up into place
    When user expands the chart again
    Then it should animate back in

  Scenario: Pro order form Size (USD) slider matches Figma
    Given user is on the Pro order form with the "Size (USD)" input visible
    Then the size slider should appear visually small (thumb/track/dots matching Figma), with adequate spacing above it
    When user taps the "Size (USD)" label
    Then the numeric keyboard should open and the input should be focused
    When user drags the slider thumb near its edges
    Then the drag should register normally, without a smaller-than-expected touch target
```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

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

### **Before**

N/A

### **After**



https://github.com/user-attachments/assets/61951ed5-bec8-4308-bc52-795a47f47b0c



## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [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.

#### Performance checks (if applicable)

- [x] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

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

<!-- Generated with the help of the pr-description AI skill -->

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches live balance/add-funds/withdraw flows and geo-eligibility in
the new sheet, plus scroll-linked header animation and market data
enrichment—mostly UI but with real money-adjacent actions.
> 
> **Overview**
> Adds **`PerpsBalanceBottomSheet`** so the Pro header wallet control
opens balance, available funds, P&L, withdraw/add funds, and activity
**on the market screen** instead of navigating to Perps home.
> 
> The Pro header gains **scroll-driven crossfade** from the perp-pair
subtitle to a compact live price (`useHeaderStandardAnimated`,
`LivePriceHeader` **`prominent`** size). **`PerpsMarketIdentity`**
accepts custom **`subtitleContent`** for that row.
> 
> **`usePerpsMarkets`** enriches route markets missing formatted
**`maxLeverage`** (deep links / minimal params), with
**`skipInitialFetch`** when leverage is already present.
> 
> **Layout & motion:** `ScrollView` → **`Animated.ScrollView`**; chart
expand/collapse and order-book column use **fade + `LinearTransition`**.
Order-book **expand** moves to the order form (**book icon** beside
long/short). Order-book **buy/sell-only toggle** is hidden; depth bars
animate on ticks.
> 
> **Order form UX:** compact **`PerpsSlider`** via scale wrapper; **Size
(USD)** label focuses input; shared **`px-2`** inset via layout. Wallet
handling removed from **`usePerpsProMarketHeaderActions`** in favor of
local sheet state.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
096f7b4. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->
Bump `@metamask/money-account-balance-service` to `^2.4.0`. Needed to
convert Veda API's APR to APY.
<!--
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**

<!-- mms-check: type=changelog required=true blocking=true -->

<!--
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: update @metamask/money-account-balance-service to
^2.4.0

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes: [MUSD-1229: Update money-acount-balance-service in Mobile app +
Ensure we're not compounding clientside
already](https://consensyssoftware.atlassian.net/browse/MUSD-1229)

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

N/A - package bump

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

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

### **Before**

<!-- [screenshots/recordings] -->
N/A - package bump

### **After**

<!-- [screenshots/recordings] -->
N/A - package bump

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [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.

#### Performance checks (if applicable)

- [x] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes how Money account yield (APY) is derived for user-facing
balances and copy, with no in-repo code review of the package
diff—incorrect rates would be a product/trust issue rather than an auth
or data breach.
> 
> **Overview**
> Updates **`@metamask/money-account-balance-service`** from **^2.3.0**
to **^2.4.0** in `package.json` and refreshes **`yarn.lock`**. The
resolved **2.4.0** package now pulls
**`@metamask/money-account-api-data-service` ^0.4.0** as a transitive
dependency (replacing the older **^0.2.0** tree entry in the lockfile).
> 
> There are **no application source changes** in this PR—Money UI
continues to consume balances/APY via existing hooks such as
`useMoneyAccountBalance`. The bump is intended to pick up library
behavior for **Veda API APR→APY** handling and to avoid
**double-compounding yield on the client** (per MUSD-1229).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
c0606cf. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

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

Sets up feature flag for DeFi positions v2 and initialises new DeFi
controller.

The old controller remains the same, but is disabled when the new
feature flag is enabled.
The new controller is only enabled when the new feature flag is enabled.
The old feature flag has no impact.

There is a follow up PR with all the UI work needed to display the state
from the new controller, and there is a task to remove the old flag and
old controller when the new one becomes stable in prod.

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

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

<!-- mms-check: type=issue-link required=true -->

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

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

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

<!-- mms-check: type=screenshot required=true -->

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

### **Before**

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

### **After**

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

Should not display any changes, as it just initialises controller and
the FF is off.

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [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.

#### Performance checks (if applicable)

- [X] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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 Engine composition and mutually exclusive DeFi data paths
behind a flag (default off); mis-flagging could disable positions or run
the wrong controller, but rollout is controlled and well-tested at
init/selector level.
> 
> **Overview**
> Introduces **`DeFiPositionsControllerV2`** into the mobile Engine
alongside the existing DeFi positions controller, gated by a new remote
feature flag **`defiControllerV2`** (default off).
> 
> **V2 init** wires the `@metamask/assets-controllers` controller with a
cached **`createApiPlatformClient`** (bearer token via
`AuthenticationController`, currency from `AssetsController`). It runs
only when basic functionality, completed onboarding, and the V2 flag are
all true.
> 
> **V1** `isEnabled` now also requires
**`!selectDefiControllerV2Enabled`**, so only one controller fetches
positions at a time. Homepage selectors split the same way:
**`selectDeFiPositionsSectionEnabled`** turns off when V2 is on;
**`selectDeFiPositionsV2SectionEnabled`** is the V2 UI gate.
> 
> Supporting changes register messengers, persist
**`DeFiPositionsControllerV2`** state, subscribe to
**`DeFiPositionsControllerV2:stateChanged`**, extend
fixtures/logs/tests, and document the flag in the feature-flag registry.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f05ce2e. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
#32387)

## **Description**

This PR integrates a daily anonymizer into the developer usage-metrics
collection tooling.

The usage-tracking Yarn plugin now opportunistically triggers the
anonymizer once per 24h window: the first non-CI `yarn <script>` run
after the window opens spawns the anonymizer as a detached, non-blocking
child process. The 24h gate is read from `last_run_at` in
`~/.tool-usage-collection/anonymizer-state.json`; the anonymizer
re-checks and claims the window itself, so concurrent spawns are
harmless. The trigger is best-effort and never throws into the Yarn hot
path — failures are written to a local `anonymizer.log`.

The anonymizer itself is published as
[`@metamask/tooling-insight`](https://github.com/MetaMask/experimental-tooling-insight)
and consumed here as a `devDependency`, pinned to a specific preview
build. The trigger is disabled when `CI` is set or
`TOOL_USAGE_COLLECTION_OPT_IN=false`, consistent with the rest of the
collection tooling.

Also cleans up `scripts/tooling/README.md` (trims the inlined
dev-tooling-explorer instructions in favor of linking its repo,
documents the daily anonymizer) and removes the now-unused
`scripts/tooling/tsconfig.json`.

Uses the package [tooling-insight
1.0.0](https://www.npmjs.com/package/@metamask/tooling-insight)

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Refs:
[MCWP-644](https://consensyssoftware.atlassian.net/browse/MCWP-644)

## **Manual testing steps**

N/A — developer-only tooling, disabled in CI. Verified via unit tests in
`.yarn/plugins/plugin-usage-tracking.test.ts`:

1. Run `yarn jest .yarn/plugins/plugin-usage-tracking.test.ts`.
2. Confirm the anonymizer is not spawned when `last_run_at` is within
24h.
3. Confirm the plugin is disabled (no spawn) when `CI` is set.

## **Screenshots/Recordings**

N/A — non-user-facing developer tooling change.

### **Before**

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

### **After**

Example logs from `tail -f ~/.tool-usage-collection/anonymizer.log`:
```
{"ts":"2026-07-30T12:07:25.806Z","cli":"anonymizer","level":"info","message":"push complete","extra":{"status":200}}
{"ts":"2026-07-30T12:07:25.810Z","cli":"anonymizer","level":"info","message":"publish complete","extra":{"latestDay":"2026-07-27","sampleCount":410}}
```
Example state `~/.tool-usage-collection/anonymizer-state.json` file:
```json
{
  "version": 1,
  "instance_uuid": "test",
  "last_pushed_day": "2026-07-27",
  "last_run_at": "2026-07-30T12:07:24.665Z"
}
```


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

#### Performance checks (if applicable)

- [x] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

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


[MCWP-644]:
https://consensyssoftware.atlassian.net/browse/MCWP-644?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Developer-only Yarn plugin and local opt-out/CI guards; no mobile app
runtime changes. Residual risk is limited to optional background
anonymizer runs on developer machines when collection is enabled.
> 
> **Overview**
> Adds **`@metamask/tooling-insight`** as a dev dependency and wires the
usage-tracking Yarn plugin to **spawn `daily-anonymizer.mjs` in the
background** after a logged root script finishes, gated by a **24h
`last_run_at`** check in
`~/.tool-usage-collection/anonymizer-state.json` (skipped in CI/opt-out;
errors go to `anonymizer.log` without affecting `yarn`).
> 
> **Yarn event logging is tightened** so only **user-typed root
scripts** are recorded: `MM_TOOL_USAGE_PARENT` is set at **module load**
(so nested `yarn` children and repeated `factory()` calls are handled
correctly), **install lifecycle scripts** are ignored, and
**interrupted** runs are detected via a broader set of signal exit codes
plus **SIGINT/SIGHUP/SIGTERM listeners** when exit codes are ambiguous.
> 
> Docs in `scripts/tooling/README.md` describe root-only tracking,
interrupted events, and the daily anonymizer;
**`scripts/tooling/tsconfig.json` is removed**; depcheck ignores the new
package.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
2e78419. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Signed-off-by: Nicolas MASSART <nicolas.massart@consensys.net>
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

Adds Appium smoke coverage for wallet platform flows under
`tests/smoke-appium/wallet/`, continuing the MMQA-2006 migration to
Playwright + Appium.

This PR includes:
- Incoming transactions Appium smoke coverage
- EVM provider events Appium smoke coverage (accountChanged /
chainChanged via native UI)
- mUSD conversion happy path Appium smoke: First Time User and Asset
Overview (classic conversion with Money Hub off)
- Supporting mocks and POM updates (intents relay quote/status hosts,
WalletView mUSD/asset locators, NetworkConnectMultiSelector Appium row
locators, confirmation Done-button wait)

### Appium specs added

| Spec | Cases |
| --- | --- |
| `incoming-transactions.spec.ts` | Incoming transfer visibility /
activity |
| `connections/evm-provider-events.spec.ts` | Permitted dapp notified of
account and chain changes |
| `musd-conversion-happy-path.spec.ts` | First Time User USDC→mUSD;
Asset Overview USDC→mUSD |

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

CHANGELOG entry: null

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes: https://consensyssoftware.atlassian.net/browse/MMQA-2006

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Wallet Appium smoke (MMQA-2006)

  Scenario: run mUSD conversion happy path on Android
    Given a main-e2e release APK is available at build/ci-main-e2e/app-prod-release.apk
    And Android emulator-5554 is booted
    When I run yarn appium-smoke:android --grep "mUSD Conversion Happy Path"
    Then First Time User and Asset Overview cases pass

  Scenario: run EVM provider chain-permission case on iOS and Android
    Given a main-e2e MetaMask.app / APK is installed
    When I run yarn appium-smoke:{ios|android} --grep "notifies a permitted dapp of the new chain ID when the network changes"
    Then the case passes on both platforms
```

Local validation performed:
- Android (`emulator-5554`): mUSD Conversion Happy Path — 2 passed
- Android + iOS: EVM provider chain ID / network permission case —
passed

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

N/A — E2E/test-only changes; no product UI changes.

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

- [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.

#### Performance checks (if applicable)

- [x] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

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

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

---------

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

Fixes High-severity list recycling in Add Asset token search
(`SearchTokenResults`).

The token-search `FlashList` keyed rows by array index and defined
`renderItem` inline. As search results shift on every keystroke, index
keys force full remounts instead of cheap recycles and can attach
selection state to the wrong row.

This change:
1. Keys rows by stable `${chainId}-${address}` identity
2. Extracts a module-level `React.memo` row component and a
`useCallback` `renderItem`
3. Moves per-row selected/already-added lookups into the row path via a
memoized selected-address set
4. Adds a unit test that selection stays on the correct token when
`searchResults` reorder

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: #31314
Fixes:
[ASSETS-3722](https://consensyssoftware.atlassian.net/browse/ASSETS-3722)

## **Manual testing steps**

```gherkin
Feature: Add Asset token search selection stability

  Scenario: selection stays on the correct token while refining search
    Given the user is on Add Asset search with multiple token results

    When the user selects a token
    And then types or deletes characters so the result list reorders
    Then the previously selected token remains selected
    And no unrelated row appears selected
```

Unit coverage: `yarn jest
app/components/Views/AddAsset/components/SearchTokenResults/SearchTokenResults.test.tsx
--coverage=false` (7 passed).
Also verified: `npx eslint` on touched files; `yarn lint:tsc`.

## **Screenshots/Recordings**

N/A — performance/recycling fix; no intentional UI change.

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

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


<div><a
href="https://cursor.com/agents/bc-dbda72c5-a276-4b2f-87ec-b43641e4be31"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/automations/ad0b477a-8482-11f1-a7d1-d6b4613131ce"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/view-automation-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/view-automation-light.png"><img
alt="View Automation" width="141" height="28"
src="https://cursor.com/assets/images/view-automation-dark.png"></picture></a>&nbsp;</div>



[ASSETS-3722]:
https://consensyssoftware.atlassian.net/browse/ASSETS-3722?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Scoped UI/list recycling fix in Add Asset search with unit test
coverage; no auth, persistence, or API changes.
> 
> **Overview**
> Fixes **incorrect checkbox/selection state** in Add Asset token search
when the result list reorders as the user types.
> 
> `SearchTokenResults` now keys `FlashList` rows with
**`${chainId}-${address}`** instead of array index, and uses a memoized
**`SearchTokenResultRow`** with a stable **`useCallback` `renderItem`**
and a **`Set` of selected addresses** so recycled rows bind to the right
token. A unit test asserts selection stays on **Token A** after
**`searchResults`** are reordered.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
158faf8. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: prithpal.sooriya <prithpal.sooriya@consensys.net>
Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

<!--
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?
-->
 What's included:

- Provider + container: PerpsProOrderFormPanel now mounts a single
PerpsOrderProvider (initialized from the route market) and a content
component that consumes usePerpsOrderContext - following the same
provider convention as lite (usePerpsProOrderForm): composes the
existing derived value hooks into display ready summary strings and a
typed notices list, owns Pro-only state (reduceOnly, sheet visibility),
and exposes a trimmed, direct path submit handler.
- Submission through usePerpsOrderExecution with the guards from lite's
direct path (validation, slippage-exceeds, cross-margin warning modal,
TP/SL-separate flip handling, toasts, pending config cleanup). Order
type moves into orderForm.type; leverage/slippage bottom sheets, TP/SL
navigation, Add Funds, and Mid-price are wired.
- Scope boundaries: pay-with-any-token/deposit-and-order is out of v1;
bespoke Pro-specific analytics trace names/abandonment are deferred to a
product/analytics sync (existing screen-viewed, place-order-tap, and
controller-owned terminal trade events are wired).
- Shared helpers: the order-sizing math, OrderParams/tracking-data
assembly, and TP/SL warning flags are pure functions (utils/orderSizing,
utils/orderParams, utils/tpslValidation) that both the Pro and lite
forms consume, so the two derive these values from one implementation.
Includes unit tests for the helpers plus branch coverage for the Pro
hook and panel.

  1. What is the reason for the change?

The Pro order form was UI-only scaffolding — it couldn't read live order
state or place an order, so the Pro market screen was non-functional for
trading. This ticket (split out from TAT-3580 to review UI and logic
independently) supplies the missing state/logic wiring.

  2. What is the improvement/solution?

A working Pro order form that behaves like the lite form (direction,
leverage, order type, limit price, size/slider, reduce-only, TP/SL,
validation banners, summary values, direct submission with toasts) while
staying on the Pro screen on submit. It's built by reusing lite's hooks
and shared pure helpers — minimizing duplication and keeping order form
behavior consistent across both forms.
  
Extracted the three repeated inline derivations (deriveOrderSizing,
getPerpsOrderTpSlWarnings, buildPerpsOrderTrackingData) that both the
lite and Pro forms were computing independently into shared pure
utilities. Two components calling the same controller functions but each
re-deriving the same values inline is still duplication — just one level
lower than it looks. With these as named, tested functions a bug fix or
edge-case correction (e.g. the TP/SL validationReferencePrice logic) is
a single edit that applies to both forms automatically, rather than a
change that must be made twice. Pure functions are also directly unit
testable with plain inputs, without spinning up hooks, context
providers, or React state - orderSizing.test.ts and
tpslValidation.test.ts cover the math paths that previously could only
be exercised through the full component. The forms now contain only
React wiring; the arithmetic lives in explicitly named, documented,
independently verified utilities..

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

<!--
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: Wired Pro mode order form to state and hooks for submit

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes: https://consensyssoftware.atlassian.net/browse/TAT-3595

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

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

<!-- mms-check: type=screenshot required=true -->

<!-- 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/0883e47a-b0de-4b77-b525-e553e5230e06



https://github.com/user-attachments/assets/144f0616-b1b8-4d0a-802e-d0e49b784190



## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [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.

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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 live perps order submission and shared sizing/params assembly
for both lite and Pro; behavior is intended to match lite but
regressions could affect margin, slippage, or post-submit TP/SL
handling.
> 
> **Overview**
> **Pro trading on the market screen** replaces the placeholder order
panel with a full flow: `PerpsOrderProvider`, `usePerpsProOrderForm`
(validation, slippage/cross-margin guards, reduce-only, TP/SL, direct
submit with toasts), and bottom sheets wrapped in **Modal** so overlays
aren’t clipped in the Pro layout. `PerpsProMarketView` drops local
order-type state and passes `market` into the panel.
> 
> **Shared order-form logic** moves repeated inline math from lite
`PerpsOrderView` into **`deriveOrderSizing`**, **`buildPerpsOrderParams`
/ `buildPerpsOrderTrackingData`**, and **`getPerpsOrderTpSlWarnings`**,
with unit tests. Lite and Pro both consume these; digit caps use
**`MAX_PERPS_INPUT_DIGITS`** across close/limit/order inputs.
> 
> **Submission correctness:** `usePerpsOrderExecution.placeOrder` now
**returns `OrderResult`**, and lite/Pro **skip TP/SL follow-up and
`clearPendingTradeConfiguration` when the order fails**.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
e964004. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: abretonc7s <107169956+abretonc7s@users.noreply.github.com>
…34037)

## **Description**

Memoizes `selectTokensByAddress` so consumers do not re-render when the
address→token map content is unchanged.

`selectTokensByAddress` previously used plain `createSelector` and
always built a fresh map via `reduce`. When `selectTokens` recomputed
with equal content under a new array reference (e.g. unrelated
`allTokens` mutations), every address-map subscriber re-rendered.

This change:
1. Switches `selectTokensByAddress` to `createDeepEqualSelector` (same
pattern as `selectAllTokensFlat` / sibling token selectors)
2. Returns a module-level frozen empty object
(`EMPTY_TOKENS_BY_ADDRESS`) for the empty case
3. Adds referential-stability unit tests (same state, equal-content
states, and empty object)

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: #31357
Fixes:
[ASSETS-3726](https://consensyssoftware.atlassian.net/browse/ASSETS-3726)

## **Manual testing steps**

```gherkin
Feature: token-by-address selector stability

  Scenario: address-keyed token lookups stay stable on unrelated store updates
    Given a wallet with tokens on the selected network

    When an unrelated Redux update occurs that does not change selected-account token contents
    Then components subscribed via selectTokensByAddress should keep a stable selector result reference
```

Unit coverage: `yarn jest app/selectors/tokensController
--coverage=false` (26 passed), including referential-stability
assertions. Also verified with `npx eslint` on touched files and `yarn
lint:tsc`.

## **Screenshots/Recordings**

N/A — selector-only performance fix; no UI changes.

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

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

<div><a
href="https://cursor.com/agents/bc-7ca6a05b-5a70-4126-b484-a9f59697ad70"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/automations/ad0b477a-8482-11f1-a7d1-d6b4613131ce"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/view-automation-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/view-automation-light.png"><img
alt="View Automation" width="141" height="28"
src="https://cursor.com/assets/images/view-automation-dark.png"></picture></a>&nbsp;</div>



[ASSETS-3726]:
https://consensyssoftware.atlassian.net/browse/ASSETS-3726?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Selector-only memoization change with unit tests; no auth,
persistence, or UI behavior changes.
> 
> **Overview**
> **`selectTokensByAddress`** now keeps a stable result reference when
the selected-account token list is unchanged, so Redux subscribers avoid
extra re-renders after unrelated token-store updates.
> 
> The selector uses **`createDeepEqualSelector`** (aligned with other
token selectors) instead of **`createSelector`**, which always produced
a new address→token map via **`reduce`**. Empty token lists return a
shared frozen **`EMPTY_TOKENS_BY_ADDRESS`** instead of a new `{}` each
time. Tests assert referential stability for repeated calls,
equal-content state, and the empty case.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
e35f28b. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: prithpal.sooriya <prithpal.sooriya@consensys.net>
Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com>
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

mirroing MetaMask/metamask-extension#44979

This PR wires Stellar-specific asset state into the mobile UI by
introducing selectors and hooks for (1) trustline
activation/deactivation and (2) native spendable-balance breakdown, then
surfaces these in the token list and token details screens.

**Changes:**
- Added Stellar selectors to detect activation requirements and compute
spendable/reserved balances from AssetsController metadata.
- Implemented Snap client request wrappers for Stellar trustline
add/delete, plus UI hooks/components to activate/deactivate assets.
- Updated token list/details UI to show an “Inactive” badge, an
activation CTA card, a “Deactivate asset” menu item, and a
spendable-balance section.


<!-- mms-check: type=text required=true -->

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

<!-- mms-check: type=changelog required=true blocking=true -->

<!--
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 Stellar Asset Component and wire them into
asset component (asset details, asset row and asset button)

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes:

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

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

<!-- mms-check: type=screenshot required=true -->

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

### **Before**

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

### **After**

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

All evm / non evm token should stay the same behaviour
https://www.loom.com/share/fd4f939c57a0467d9c9fd0c3488f88fe

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [ ] 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.

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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**
> Trustline add/delete flows submit on-chain changes via the Stellar
Snap and affect wallet asset visibility and balances, though behavior is
gated to Stellar classic/native assets with tests covering main paths.
> 
> **Overview**
> Adds **Stellar-specific asset UX** on top of new Redux selectors and
Snap trustline requests.
> 
> **Selectors & Snap:** New `stellar-assets` selectors read
`AssetsController` metadata for trustline limits, activation need, and
native XLM spendable vs reserved amounts. `changeTrustOpt` add/delete
wrappers call the Stellar wallet Snap. Asset list filtering keeps
activation-capable classic assets visible even at zero balance.
> 
> **UI:** Token rows show an **Inactive** badge when activation is
required. Token details show an **Activate** card (success →
transactions view; errors via notification) and, for native XLM,
**SpendableBalanceSection** instead of the default balance block when
spendable data exists. **More** menu adds **Deactivate asset** when the
trustline is active, with non-zero balance blocked before Snap delete.
> 
> **Hooks:** `useAssetActivation` and `useSpendableBalance` connect
components to selectors and Snap; i18n strings added for activation,
spendable balance, and deactivate copy.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
58ad51a. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…4073)

<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

Removes the `socialAiTSA905AbtestQuickBuyKeyboard` A/B test and its
associated logic so Quick Buy always shows the numeric keyboard (and no
longer offers the percentage slider).

**Why:** For **8.6.0** we want the keyboard as the only Quick Buy amount
input, so this A/B test is no longer needed.

**Why remove the flag (not just default to treatment):** On **8.5.0**, a
small bug means we need to keep the flag at **100% control**. If we left
the flag in place for 8.6.0, we would need **100% treatment** on 8.6.0
while keeping **100% control** on 8.5.0 — an unnecessarily complex
LaunchDarkly split across versions. Removing the flag in 8.6.0 avoids
that conflict.

This PR:
- Deletes the keyboard vs slider A/B config and analytics registry
mapping
- Removes `useKeyboard` branching across Quick Buy
Root/Context/footer/keypad/amount/skeleton
- Deletes `QuickBuyPercentageSlider` and the control (slider) UI path
- Leaves the separate TSA-612 Asset Details Quick Buy A/B test untouched

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

CHANGELOG entry: Updated Quick Buy to always use the numeric keyboard
for amount entry

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes: TSA-963

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Quick Buy keyboard-only amount entry

  Scenario: user opens Quick Buy and enters an amount with the keypad
    Given the user opens Quick Buy for a supported token

    When the sheet finishes opening
    Then the numeric keypad is shown by default
    And the percentage slider is not shown

    When the user types an amount on the keypad
    And taps Buy
    Then the trade flow proceeds with the entered amount

  Scenario: user selects a quick-amount pill
    Given Quick Buy is open with the keypad visible

    When the user taps a buy quick-amount pill
    Then the amount updates to that preset
    And the keypad is dismissed

    When the user taps the amount headline
    Then the keypad reopens
```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

N/A — removes an A/B branch; keyboard UI is unchanged from the treatment
path already shipping.

### **Before**

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

Control: percentage slider. Treatment: numeric keypad.

### **After**

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

Numeric keypad only (former treatment).

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

- [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.

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

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

<!-- mms-check: type=text required=true -->

Crypto-native users encountering HIP-3 tickers (e.g. NVDA, CL) often
lack context on the underlying asset, which creates a trust barrier on
stock and commodity markets. This PR adds an **About** section on the
Perps Lite market detail screen (`PerpsMarketDetailsView`) that shows
the Hyperliquid/Terminal asset description when available.

**What changed**
- New `PerpsMarketAboutSection` with title `About {assetName}`, a 3-line
collapsed description, and a bold underlined **Read more** control that
expands the full text then disappears
- Graceful fallback: the section is not rendered when the market has no
description (no empty state)
- New `usePerpsMarketAboutTracking` hook that fires
`PERPS_UI_INTERACTION` with:
- `market_about_section_displayed` when the section is rendered
(includes `market_symbol`, `market_type`, `description_length`)
- `market_about_section_viewed` once per screen session when the section
scrolls into view
- Wired into `postMarketInsightsSections` on the Lite market details
screen; description is sourced from existing
`PerpsMarketData.description` (no extra network fetch)
- Unit tests for the component, tracking hook, and view integration

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

CHANGELOG entry: Added an About section on Perps market details so users
can read a short description of the underlying asset

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Refs: TAT-3162

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Perps market About section (Lite mode)

  Scenario: user sees About when a market has a description
    Given the user is in Perps Lite mode
    And a market has a non-empty Hyperliquid/Terminal description
    When the user opens that market's detail screen
    Then an "About {asset name}" section is shown
    And the description is clamped to 3 lines when longer than 3 lines
    And a bold underlined "Read more" control is shown when truncated

  Scenario: user expands the About description
    Given the About section is shown with "Read more" visible
    When the user taps "Read more"
    Then the full description is shown
    And the "Read more" control disappears

  Scenario: user does not see About when description is missing
    Given a market has no description from Hyperliquid/Terminal
    When the user opens that market's detail screen
    Then the About section is not rendered
    And there is no empty state or placeholder text

  Scenario: analytics fire for display and view
    Given a market with a description
    When the user opens the market detail screen
    Then PERPS_UI_INTERACTION with interaction_type market_about_section_displayed fires once
    When the user scrolls the About section into the viewport
    Then PERPS_UI_INTERACTION with interaction_type market_about_section_viewed fires at most once per screen session
```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

N/A — UI screenshots not attached in this PR; please add device captures
of collapsed (3-line + Read more) and expanded About states before Ready
for review.

### **Before**

N/A — no About section on market details

### **After**
<img width="1206" height="2622" alt="Simulator Screenshot - iPhone 17 -
2026-07-29 at 16 03 07"
src="https://github.com/user-attachments/assets/5ae2fde9-3cf5-4517-8c84-1748a13ad65b"
/>

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

- [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.

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **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 Perps market details change with analytics and tests; no auth,
payments, or new network layer.
> 
> **Overview**
> Adds an **About** block on Perps Lite market details when
`PerpsMarketData.description` is present, using existing market metadata
(no new fetch).
> 
> **`PerpsMarketAboutSection`** shows “About {assetName}”, clamps copy
to three lines, and offers **Read more** (hidden measure text decides
truncation). Missing or whitespace-only descriptions render nothing.
> 
> **`usePerpsMarketAboutTracking`** gates visibility, wires `onLayout` /
`ScrollView` `onScroll`, and emits `market_about_section_displayed` and
a once-per-market `market_about_section_viewed` `PERPS_UI_INTERACTION`
with symbol, type, and description length. The section is the first
entry in `postMarketInsightsSections`; new i18n strings and test IDs
support UI and integration tests.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
144e586. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**
This PR integrates V1 of the new money utils package. This shouldn't
lead to any behaviour changes.

<!-- mms-check: type=text required=true -->

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

<!-- mms-check: type=changelog required=true blocking=true -->

<!--
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: integrate money utils v1

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes: MUSD-1238

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

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

<!-- mms-check: type=screenshot required=true -->

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

<!-- mms-check: type=checklist required=true -->

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [ ] 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.

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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**
> Refactor-only dependency extraction with stable re-exports; intended
to be behavior-neutral, though confirmation flows that use
`MUSD_TOKEN.image` now depend on the package providing that field.
> 
> **Overview**
> Adds **`@metamask/money-account-utils` ^1.0.0** and moves shared mUSD
token metadata, chain maps, asset IDs, and helpers (`isMusdToken`,
`getTokenDisplaySymbol`, money-account chain guards, etc.) out of
**`app/components/UI/Earn/constants/musd.ts`**, re-exporting them so
existing imports from that path stay stable.
> 
> **`MUSD_TOKEN`** is now built by spreading the package’s `MUSD_TOKEN`
and attaching the mobile-only **`imageSource`** (local PNG).
Earn-specific config (buyable chains, APY, geo fallback, toast delay)
remains in the local file. Inline definitions of addresses, decimals,
and guard functions are removed from mobile in favor of the shared
package.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
2580bee. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
## **Description**

When a MetaMask Pay quote fails (e.g. insufficient balance), the
confirmation screen previously showed a generic "No quotes available"
message with no explanation. Core now returns a structured error on each
quote; this PR surfaces it.

- Adds a `NoQuoteAlert` component that shows a reason-appropriate
collapsed message (`insufficient-source-balance` → "Insufficient
balance"; anything else → the generic string), with a double-tap to
toggle a full error view showing core's `message` and `detail` rows.
- Wires the alert into the existing "Pay with" row alert system via a
new selector, hook, and `content` prop on `AlertMessage` — the alert
blocks confirm while prices/fees continue to render.
- Fixes the post-quote "no quotes" check so same-token withdraw flows
(e.g. MUSD → MUSD) correctly surface an alert when their amounts list is
empty.

Depends on MetaMask/core#9143, which adds the structured `quoteError`
(`message`, `detail`, `reason`) to each pay quote.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Refs: MetaMask/core#9143

## **Manual testing steps**

```gherkin
Feature: Pay quote error surfaced in confirmation alert

  Scenario: a pay quote can't be used
    Given a transaction that requires a MetaMask Pay quote
    And the selected pay token produces a quote that can't be used

    When the confirmation screen loads
    Then a blocking alert is shown on the "Pay with" row
    And the confirm button is disabled

  Scenario: tapping the alert reveals the full error
    When the user double-taps the alert
    Then the full error message and detail rows are shown
    And double-tapping again collapses it
```

## **Screenshots/Recordings**

N/A

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

#### Performance checks (if applicable)

- [ ] I've tested on Android
- [ ] I've tested with a power user scenario
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics

## **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 confirmation blocking behavior and pay quote error UX on the
critical confirm path, but scope is UI wiring and read-only controller
state with tests.
> 
> **Overview**
> When MetaMask Pay returns a quote that fails validation (e.g.
insufficient balance), confirmations now show a **blocking “Pay with”
alert** with a reason-specific collapsed message instead of only the
generic “no quotes” copy. Core’s structured `quoteError` is read per
transaction via a new selector and `useTransactionPayQuoteError`, and
`useNoPayTokenQuotesAlert` treats a present `quoteError` as a separate
show condition while still blocking confirm.
> 
> A new **`NoQuoteAlert`** component renders that error: double-tap
toggles between the collapsed string (`insufficient-source-balance` uses
the insufficient-balance i18n key) and the full `message` plus optional
`detail` rows. **`AlertMessage`** gains an optional `content` slot (with
layout split into `content` vs `message` styles), and the custom-amount
flow passes **`alertContent`** from the alert system so rich UI can
replace plain banner text.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
a9c3eb4. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ty helpers (#34111)

## **Description**

Refactors `getMetaMaskPayProperties` in
`app/core/Engine/controllers/transaction-controller/metrics_properties/metamask-pay.ts`
for readability. The builder had grown into a hard-to-follow mix of
inline branching and a ~130-line `addPayTypeProperties` doing six
unrelated jobs.

Changes:

- **Root function is now a flat, annotated composition** — each helper
call is preceded by the exact `mm_pay_*` properties it sets, so the full
metric surface is visible at a glance.
- **Split into small, single-purpose helpers**:
`addPolymarketAccountCreated`, `addBaselinePayProperties`,
`addAmountProperties`, `addQuoteProperties`, `addFiatPaymentProperties`,
`addChildTransactionStep`, `addDustProperties`, `addTimeToComplete`,
plus shared `getTransactionPayData` / `isSwapOrBridge` /
`isPayTransaction` utilities.
- **Maximum metrics when `TransactionPayController.transactionData` is
unavailable**: since `transactionData` is not persisted but
`transactionMeta.metamaskPay` is, the old startup-error-only backfill
(`addFailedOnStartupMetrics`) is generalized into
`addPersistedPayMetadata`. Whenever `transactionData` is missing, we now
backfill `mm_pay_receiving_value_usd`, `mm_pay_provider_fee_usd`,
`mm_pay_network_fee_usd`, `mm_pay_strategy` and `mm_pay_fiat_provider`
from the persisted metadata, regardless of the error message.
- **Payment method recovered from the persisted Ramps order**: for
fiat-funded transactions in the backfill path,
`mm_pay_payment_method_selected` is resolved by joining
`metamaskPay.fiat.orderId` against `RampsController.orders` (which IS
persisted, `providerOrderId` match — same join
`useFiatPaymentMethodName` uses) and normalizing
`order.paymentMethod.id` via the existing
`normalizeMetaMaskPayPaymentMethod`. Falls back to a generic `'fiat'`
value when the order isn't in cache or has no payment method, so
fiat-funded transactions are never misreported as `'crypto'`.
- **`mm_pay_strategy` defaults to `'relay'` for non-fiat backfills**:
the non-fiat strategy isn't persisted on `metamaskPay` yet, so the
backfill path temporarily assumes the most common strategy. To be
replaced once strategy info is persisted in TransactionController's
`metamaskPay` state.
- Removed redundant conditions (`isPayType || properties.mm_pay`) and
the mutate-order coupling between helpers; `txPayData` is resolved once
at the top and threaded through.

No behavior change other than the intentional backfill changes above.
Tests updated/extended accordingly (68 passing).

### Property coverage matrix

Scope: pay transaction, parent/standalone path (`isPayTransaction`
true).

<details>
<summary><b>When <code>txPayData</code> EXISTS (live controller
state)</b></summary>

**Guaranteed (unconditional):**

| Property | Source |
|---|---|
| `mm_pay` | `true`, always |
| `mm_pay_payment_method_selected` | `'crypto'` default, overridden by
fiat method if `fiatPayment.selectedPaymentMethodId` |
| `mm_pay_quote_skipped` | quote count comparison, always a boolean |
| `mm_pay_transaction_step_total` | `quotes.length + 1`, always |
| `mm_pay_transaction_step` | `= step_total`, always |

**Conditional:**

| Property | Set when |
|---|---|
| `mm_pay_chain_selected` | `metamaskPay.chainId` exists |
| `mm_pay_token_selected` | `paymentToken.symbol` or TokensController
lookup succeeds |
| `mm_pay_use_case` | type matches `USE_CASE_MAP` |
| `mm_pay_sending_value_usd` | a token with `skipIfBalance: false`
exists |
| `mm_pay_receiving_value_usd` | `totals` exists |
| `mm_pay_metamask_fee_usd` | `totals` exists |
| `mm_pay_provider_fee_usd` | `totals` exists |
| `mm_pay_network_fee_usd` | `totals` exists |
| `mm_pay_strategy` | first real quote strategy is Relay or Fiat |
| `mm_pay_fiat_provider` | fiat method selected + rampsQuote provider
parses |
| `mm_pay_fiat_token_target` | fiat method selected +
`cryptoTranslation.symbol` |
| `mm_pay_fiat_chain_target` | fiat method selected + chain resolvable
from caipAssetId/rampsQuote |
| `mm_pay_time_to_complete_s` | event is FINALIZED + a numeric
`submittedTime` |
| `polymarket_account_created` | type is predictDeposit /
predictDepositAndOrder (always set for those, path-independent) |

</details>

<details>
<summary><b>When <code>txPayData</code> is MISSING (restart / failure /
state cleared)</b></summary>

**Guaranteed (unconditional):**

| Property | Value |
|---|---|
| `mm_pay` | `true` |
| `mm_pay_payment_method_selected` | fiat: normalized method from the
persisted Ramps order (`orderId` → `providerOrderId` join), or generic
`'fiat'` on cache miss; `'crypto'` for non-fiat |
| `mm_pay_strategy` | `'fiat'` if `metamaskPay.fiat` exists, else
`'relay'` (temporary assumption until strategy is persisted; requires
`metamaskPay` to exist) |

**Conditional (backfilled from persisted `transactionMeta.metamaskPay` /
`RampsController.orders`):**

| Property | Set when |
|---|---|
| `mm_pay_chain_selected` | `metamaskPay.chainId` persisted |
| `mm_pay_token_selected` | TokensController lookup succeeds (no
`paymentToken` fallback) |
| `mm_pay_use_case` | type matches `USE_CASE_MAP` |
| `mm_pay_receiving_value_usd` | `metamaskPay.targetFiat` persisted |
| `mm_pay_provider_fee_usd` | `metamaskPay.bridgeFeeFiat` persisted |
| `mm_pay_network_fee_usd` | `metamaskPay.networkFeeFiat` persisted |
| `mm_pay_fiat_provider` | `metamaskPay.fiat.provider` parses |
| `mm_pay_time_to_complete_s` | same conditions as live path (does not
need `txPayData`) |
| `polymarket_account_created` | same conditions as live path |

**NEVER set (not recoverable — not persisted anywhere):**

- `mm_pay_sending_value_usd`
- `mm_pay_metamask_fee_usd`
- `mm_pay_quote_skipped`
- `mm_pay_transaction_step` / `mm_pay_transaction_step_total`
- `mm_pay_fiat_token_target` / `mm_pay_fiat_chain_target`

</details>

The child-transaction path additionally always sets
`mm_pay_transaction_step`, and conditionally
`mm_pay_payment_method_available` / `mm_pay_payment_method_presented`
(from parent UI metrics) and `mm_pay_dust_usd` (requires `txPayData`
quotes).

**Known caveats (backfill path):**

- `mm_pay_payment_method_selected` falls back to a generic `'fiat'` for
fiat transactions when the Ramps order isn't in the persisted
`RampsController.orders` cache (e.g. order created on another device,
wiped storage) or the order has no `paymentMethod` — the specific method
(card vs bank transfer) can't be recovered in that case.
- `mm_pay_strategy: 'relay'` for non-fiat backfills is an assumption,
not a measurement — non-fiat strategies (relay/across/server) aren't
persisted on `metamaskPay`. Follow-up: persist the strategy in
TransactionController's `metamaskPay` state and replace the assumption.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/CONF-1747

## **Manual testing steps**

N/A — covered by unit tests (`yarn jest
app/core/Engine/controllers/transaction-controller/metrics_properties/metamask-pay.test.ts`,
68 passing). No user-facing behavior change.

## **Screenshots/Recordings**

N/A — no UI changes.

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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.

#### Performance checks (if applicable)

- [ ] I've tested on Android
- [ ] I've tested with a power user scenario
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics

## **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**
> Intentional analytics semantics change when in-memory pay state is
lost; non-fiat strategy and missing Ramps orders use assumed defaults
(`relay`, `fiat`) that can mislabel events until strategy is persisted.
> 
> **Overview**
> **Refactors** `getMetaMaskPayProperties` into a flat pipeline of
single-purpose helpers (`addBaselinePayProperties`,
`addAmountProperties`, `addQuoteProperties`, `addFiatPaymentProperties`,
`addPersistedPayMetadata`, etc.) so which `mm_pay_*` keys each path sets
is visible at the top level.
> 
> **Behavior change when `TransactionPayController.transactionData` is
missing** (e.g. restart mid-flow): the old startup-error-only backfill
is replaced by **`addPersistedPayMetadata`**, which always runs in that
case. It fills receiving value and fee fields from persisted
`transactionMeta.metamaskPay`, sets **`mm_pay_strategy`** to `fiat` when
`metamaskPay.fiat` exists or **`relay`** otherwise, parses
**`mm_pay_fiat_provider`**, and resolves
**`mm_pay_payment_method_selected`** by matching `fiat.orderId` to
persisted **`RampsController.orders`** (normalized payment method, else
`'fiat'` for fiat flows; crypto flows keep `'crypto'`). Live controller
state still wins when `transactionData` exists.
> 
> **`mm_pay_time_to_complete_s`** is only computed when `mm_pay` is
already set on the finalized parent path. Unit tests are expanded for
the new backfill matrix (including `mm_pay_strategy: 'relay'` when only
`chainId` is on `metamaskPay`).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
210b376. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…stry with production default rpc (#34068)

<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

Registers the existing `moneyAccountBalanceSource` remote feature flag
in the app-level feature flag registry so production-accurate E2E mocks
include its default `rpc` routing policy and the feature-flag pipeline
recognizes it.

This registry entry does not enable or participate in runtime
segmentation. LaunchDarkly targeting already resolves the flag into
`RemoteFeatureFlagController`, and `MoneyAccountBalanceService` consumes
that value directly. The accompanying messenger test verifies that
remote feature-flag state changes reach the service. This change
therefore restores E2E and pipeline parity with the existing production
flag without changing runtime routing behavior.

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

CHANGELOG entry: null

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Refs: No linked issue — this is app-level registration for an existing
production remote feature flag.

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

N/A — there is no user-facing behavior to exercise manually. The
registry value and existing Engine messenger wiring are covered by
focused unit tests.

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

N/A — there are no user-interface changes.

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [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.

#### Performance checks (if applicable)

- [x] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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**
> Registry and test-only changes; no production logic or UI behavior is
modified in the diff.
> 
> **Overview**
> Registers the **`moneyAccountBalanceSource`** remote feature flag in
the app feature-flag registry with production default **`rpc`**, so E2E
mocks and production-default flag maps match what
**`MoneyAccountBalanceService`** already reads at runtime.
> 
> A registry unit test asserts **`moneyAccountBalanceSource`** resolves
to **`rpc`** in **`getProductionRemoteFlagDefaults`**. The money account
balance service messenger test now also expects
**`RemoteFeatureFlagController:stateChange`** to be delegated alongside
the existing balance-related actions, documenting that LaunchDarkly
updates can refresh balance routing without new wiring in this PR.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
328e1e8. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**

<!-- mms-check: type=text required=true -->

Polishes the Perps Pro market trading area so form/order-book spacing
matches the Positions panel, and surfaces available balance under the
size input.

1. **Reason:** Screen-edge padding on the Pro form/book row drifted from
the Positions section (`px-2`), and traders lacked a clear
available-balance affordance next to size.
2. **Solution:** Use an 8px (`px-2`) horizontal inset on the trading
layout; move form/book styles into dedicated `.styles.ts` files with the
separator on the form panel; show a tappable `$XX available` row that
opens add funds.

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

CHANGELOG entry: Improved Perps Pro order form layout alignment and
added available balance under size

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes:

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Perps Pro trading layout and available balance

  Scenario: trading area aligns with Positions panel
    Given the user opens a Perps market in Pro mode with the order book visible
    Then the left edge of the order form aligns with the Positions tab content
    And the right edge of the order book aligns with Positions content
    And a vertical separator appears between the form and order book with 16px inset on each side

  Scenario: available balance opens add funds
    Given the user is on the Pro order form with an initialized Perps balance
    When the user taps the available balance row under Size
    Then the add-funds / deposit flow opens
```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

- [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.

#### Performance checks (if applicable)

- [x] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **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 layout and presentation changes in Perps Pro with tests
updated; add-funds still uses existing callbacks, not new payment logic.
> 
> **Overview**
> Aligns the **Perps Pro** trading row with the Positions panel and
improves the order form UX.
> 
> **Layout:** `PerpsProMarketLayout` drops the fixed 682px min height
and the standalone vertical divider column in favor of content-driven
heights, **8px** horizontal inset (`PRO_SCREEN_HORIZONTAL_INSET`), and
styles moved into `PerpsProMarketLayout.styles.ts`. The form/book
separator is now a **right border + 16px padding** on
`PerpsProOrderFormPanel` when the order book is visible
(`PerpsProOrderFormPanel.styles.ts`). The order book panel uses full
width instead of `flex-1`.
> 
> **Order form:** Available balance under size is a single tappable row
(`AvailableBalanceRow`) that opens add funds, with screen-reader
label/hint. Slippage uses a dedicated pressable with edit icon. Summary
`KeyValueRow`s override default horizontal padding so
margin/liquidation/slippage/fees line up with the form.
`usePerpsProOrderForm` formats balance as localized `"{{amount}}
available"` and shows `"-- available"` until Perps is initialized.
> 
> **i18n:** New `perps.pro_order_form.available_balance` /
`available_balance_unavailable` across locale files.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
be0fa55. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

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

Migrates the Background Events Snap Detox smoke suite to Appium.

- Moves `tests/smoke/snaps/test-snap-background-events.spec.ts` →
`tests/smoke-appium/snaps/` then converts to Appium with
`withSnapsFixtures`.
- Serial suite: first test uses `restartDevice: true` +
`loginAndOpenTestSnaps()` + install; later tests use `restartDevice:
false` (no re-login).
- Extends `withSnapsFixtures` to pass through `restartDevice` (and
related fixture options) and updates Android Test Snaps native helper to
re-export scroll labels from selectors.
- Skips Android CI cold-boot stabilize when the emulator is already
booted, so session reuse is not disrupted and between-test session setup
is faster.

Split from the bulk approach in #34056 / #33898.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Refs: #34056
Refs: #33898

## **Manual testing steps**

N/A — E2E-only migration; coverage is Appium `SmokeSnaps` CI. Suggested
local check:

```bash
ANDROID_APK_PATH=build/ci-main-e2e/app-prod-release.apk yarn appium-smoke:android tests/smoke-appium/snaps/test-snap-background-events.spec.ts
```

## **Screenshots/Recordings**

N/A — test-only change; no user-facing UI.

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **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 to E2E harness and emulator boot logic; no
production app behavior.
> 
> **Overview**
> Moves **Background Events Snap** coverage from Detox
(`tests/smoke/snaps/`) to Appium (`tests/smoke-appium/snaps/`), using a
**serial** suite where only the first case restarts the device, logs in,
and installs the snap; later cases set `restartDevice: false` and reuse
the same session and Test Snaps page.
> 
> **`withSnapsFixtures`** now forwards `restartDevice`, mocks,
analytics, and local-node options, and adds
**`parseTestSnapStringResult` / `readTestSnapStringResult`** so
cancel/list flows work when Android returns bare strings instead of
JSON-quoted text. Android scroll label maps are **re-exported from**
`TestSnaps.selectors` instead of living in the native helper.
> 
> Timing is tuned for slower Appium/Android (e.g. 30s date offset, 10s
duration, polling timeouts). **`EmulatorHelpers`** skips cold-boot
stabilize when `sys.boot_completed` is already `1`, so reused emulator
sessions are not reset between serial tests.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
1f5d402. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Three inline component definitions inside `custom-amount-info.tsx` have
been extracted to their own directories under
`app/components/Views/confirmations/components/custom-amount/`:

- `BuySection` → `CustomAmountBuy`
- `Quote` (+ private `PaymentDetailsSkeleton` helper) →
`CustomAmountTotals`
- `ConfirmButton` (+ private `useButtonLabel` hook) →
`CustomAmountConfirmButton`

Each extracted component retains identical props and behaviour. The
parent file is updated to import and use the new components. This
improves discoverability, makes each component independently testable,
and reduces the size of the `custom-amount-info.tsx` file by ~200 lines.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

N/A — pure refactor, no behavioural change. Existing unit tests cover
the extraction.

## **Screenshots/Recordings**

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

## **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**
> Structural refactor with preserved props and logic; confirmation/pay
UX paths are unchanged aside from file layout.
> 
> **Overview**
> **Refactors** the custom amount confirmation UI by moving three inline
blocks out of `custom-amount-info.tsx` into `components/custom-amount/`,
without changing behavior.
> 
> `BuySection` becomes **`CustomAmountBuy`** (ramp buy CTA and
perps/predict copy). **`Quote`** and its skeleton helper become
**`CustomAmountTotals`** (bridge fee/time rows, total vs receive by
stage). **`ConfirmButton`** and **`useButtonLabel`** become
**`CustomAmountConfirmButton`**.
> 
> The parent only swaps imports and JSX (`<CustomAmountBuy />`,
`<CustomAmountTotals />`, `<CustomAmountConfirmButton />`) and drops
~200 lines of local helpers. **Dedicated unit tests** cover the
extracted pieces; overlapping cases were removed from
`custom-amount-info.test.tsx`.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
de510e4. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…34107)

<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

Sentry reports \`getBearerToken - unable to proceed, wallet is locked\`
from the Top Traders path. The stack is:

\`\`\`
queryFn (SocialService:fetchLeaderboard)
  → SocialService.#getAuthHeaders
  → AuthenticationController.getBearerToken
  → assertIsUnlocked  // throws while locked
\`\`\`

A previous fix gated \`useTopTraders\` with \`enabled: isUnlocked\`, but
AppState foreground still raced ahead of the React commit:
\`ReactQueryService\` marks TanStack focused while \`enabled\` could
still be true, and \`react-data-query\` uses \`staleTime: 0\`, so
\`queryFn\` ran while locked.

This PR keeps the unlock \`enabled\` gate and disables
\`refetchOnWindowFocus\` / \`refetchOnReconnect\` on that query so
automatic refetches cannot hit \`getBearerToken\` during the race. When
the wallet unlocks, \`enabled\` flips true and TanStack fetches again
(Homepage and deeplinked leaderboard both use this hook).

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

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

<!-- mms-check: type=issue-link required=true -->

Fixes: https://consensyssoftware.atlassian.net/browse/TSA-962

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

\`\`\`gherkin
Feature: Top traders fetch while locked

  Scenario: leaderboard does not fetch while locked
    Given the social leaderboard feature flag is enabled
    And the wallet auto-locks on background
When the app is backgrounded and then foregrounded while still locked
Then no SocialService fetchLeaderboard / getBearerToken locked error is
thrown

  Scenario: leaderboard loads after unlock
    Given the social leaderboard feature flag is enabled
    And the wallet is locked
    When the user unlocks the wallet
Then useTopTraders enables and loads leaderboard data on Homepage / Top
Traders
\`\`\`

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

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

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See \`docs/readme/ready-for-review.md\` for the full
checklist
semantics.
-->

- [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.

#### Performance checks (if applicable)

- [x] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [\`trace()\`](/app/util/trace.ts) for usage and
[\`addToken\`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See \`docs/readme/ready-for-review.md\`.
-->

- [ ] 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**
> Narrow change to one social leaderboard query’s TanStack options; no
auth logic changes, with tests updated for the new flags.
> 
> **Overview**
> Fixes **Sentry errors** when the Top Traders leaderboard runs
`fetchLeaderboard` while the wallet is locked (`getBearerToken` throws).
> 
> `useTopTraders` already gates the query with `enabled: isUnlocked`,
but **AppState foreground** can still trigger a TanStack refetch before
React applies `enabled: false` after auto-lock (`staleTime: 0` + focus
manager). This PR sets **`refetchOnWindowFocus: false`** and
**`refetchOnReconnect: false`** on that query so automatic refetches
cannot hit auth while locked; unlock still re-enables the query and
loads data.
> 
> Unit tests now assert those refetch flags alongside the existing
`enabled` behavior.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
0709d67. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
…tes (#34104)

## **Description**

Restores Detox-style serial session reuse for Appium Snap suites that
were collapsed into a single Playwright test during the initial
migration.

**Merge order:** stacked on
[#34101](#34101). After
#34101 merges to `main`, retarget this PR’s base to `main` and merge.

- Splits `wasm`, `installed`, and `client-status` back into
connect/setup + follow-up cases.
- Serial suites: first test uses `restartDevice: true` +
`loginAndOpenTestSnaps()` + install; later tests use `restartDevice:
false` (no re-login).
- Background Events cancel: call `blurActiveWebViewInput()` after
filling the cancel event id so the Android keyboard does not block later
Test Snaps controls (`cancel` / `getBackgroundEvents`).

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Depends on: #34101  
Refs: #34101

## **Manual testing steps**

N/A — E2E-only change; coverage is Appium `SmokeSnaps` CI. Suggested
local check:

```bash
ANDROID_APK_PATH=build/ci-main-e2e/app-prod-release.apk yarn appium-smoke:android tests/smoke-appium/snaps/test-snap-wasm.spec.ts
ANDROID_APK_PATH=build/ci-main-e2e/app-prod-release.apk yarn appium-smoke:android tests/smoke-appium/snaps/test-snap-installed.spec.ts
ANDROID_APK_PATH=build/ci-main-e2e/app-prod-release.apk yarn appium-smoke:android tests/smoke-appium/snaps/test-snap-client-status.spec.ts
ANDROID_APK_PATH=build/ci-main-e2e/app-prod-release.apk yarn appium-smoke:android tests/smoke-appium/snaps/test-snap-background-events.spec.ts
```

## **Screenshots/Recordings**

N/A — test-only change; no user-facing UI.

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

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

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **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**
> E2E test-only changes with no production code paths affected.
> 
> **Overview**
> Restores **Detox-style serial Appium runs** for WASM, installed, and
client-status Snap smoke specs by splitting each former single test into
a **connect/setup** case and one or more **follow-up** cases under
`describe.configure({ mode: 'serial', timeout: 150_000 })`.
> 
> The first test in each suite uses `withSnapsFixtures(..., {
restartDevice: true })` with `loginAndOpenTestSnaps()` and snap install;
later tests use `restartDevice: false` and only exercise snap UI (no
re-login). Background Events **schedule/list/cancel** now calls
`TestSnaps.blurActiveWebViewInput()` after filling the cancel event id
so the Android keyboard does not block cancel/get-results taps.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f07f321. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**

When paying gas with a token on Linea (e.g. mUSD), the network fee token
dropdown could show a blank or letter fallback icon if TokensController
had not hydrated `token.image` yet.

This change updates `GasFeeTokenIcon` to fall back to the CDN URL from
`getAssetImageUrl`, matching confirmation `TokenIcon`. It also uses the
token symbol for the avatar name when the image is missing.

## **Changelog**

CHANGELOG entry: Fixed missing token logos in the network fee token
dropdown when paying with a token such as mUSD

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/CONF-1739

## **Manual testing steps**

~~~gherkin
Feature: gas fee token icons

  Scenario: user sees mUSD logo in network fee token dropdown on Linea
    Given the user has mUSD on Linea
    And the user starts a send of any token on Linea

    When the user opens the network fee token dropdown
    Then mUSD shows its logo
~~~

## **Screenshots/Recordings**

N/A — pending manual verification on device/simulator.

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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.

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **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.
…QA-2147) (#34049)

<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## **Description**

<!-- mms-check: type=text required=true -->

Performance Android BrowserStack dual builds (`main-e2e-bs-with-srp` /
`main-e2e-bs-without-srp`) previously always compiled fresh on
app-change PRs, even when native sources matched a prior run's
`@expo/fingerprint`.

This aligns the performance dual-upload path with Detox E2E
(`build-android-e2e.yml`):

1. Look up prior `android-apk-main-e2e-bs-*` artifacts by fingerprint
(`find-reusable-build` across `ci.yml` / `run-performance-e2e*.yml`).
2. **Miss** → fresh dual Gradle builds (unchanged).
3. **Hit + test-only** (`main_branch_only` / `reuse_main_builds`) →
re-upload APKs as-is (app JS unchanged; same as E2E's no-repack path).
4. **Hit + app changes** → skip Gradle, `@expo/repack-app` both profiles
with current JS (env from `builds.yml`, including `IS_PERFORMANCE_TEST`
/ SRP bake-ins), then upload to BrowserStack.

`scripts/repack.js` gains optional path overrides (`REPACK_SOURCE_APK`,
etc.) so both profiles can be repacked without colliding.

Does **not** reuse Appium smoke `main-e2e` APKs (different
ABI/flags/profile). Test-only PRs still prefer BrowserStack `custom_id`
reuse on main when available; fingerprint is the fallback / app-change
savings path.

### Measured CI savings (this PR)

Same native fingerprint (`bf403cf3…`) on consecutive runs of this PR:

| Path | Run | Dual Android BS path (resolve → upload done) | Gradle
dual builds | Notes |
| --- | --- | --- | --- | --- |
| **Miss → fresh** |
[30554890417](https://github.com/MetaMask/metamask-mobile/actions/runs/30554890417)
| **~26m 32s** | with-SRP ~18m 31s, without-SRP ~18m 02s (parallel) |
Fresh compile + short BS upload (~44s) |
| **Hit → reuse + JS repack** |
[30570425894](https://github.com/MetaMask/metamask-mobile/actions/runs/30570425894)
| **~12m 27s** | **skipped** | Resolve (~49s) + Cirrus
setup/repack/upload (~11m 26s); with-SRP repack ~185s, without-SRP ~107s
|

**Wall-clock savings on the dual-build/upload path: ~14m (~53% faster)**
when fingerprint hits and app JS is repacked instead of recompiling both
BrowserStack APKs.

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

CHANGELOG entry: null

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes:
[MMQA-2147](https://consensyssoftware.atlassian.net/browse/MMQA-2147)

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Android performance BrowserStack fingerprint reuse + repack

  Scenario: test-only fingerprint hit reuses BS APKs as-is
    Given a PR with only test file changes (reuse_main_builds / main_branch_only true)
    And BrowserStack custom_id reuse did not resolve apps
    And a prior run uploaded android-apk-main-e2e-bs-with-srp and android-apk-main-e2e-bs-without-srp for the same fingerprint
    When the Build Android Dual Versions workflow runs
    Then resolve-fingerprint-reuse reports found=true
    And build-with-srp and build-without-srp are skipped
    And Upload APKs to BrowserStack re-uploads the reused APKs without repack

  Scenario: app-change fingerprint hit skips Gradle and repacks JS
    Given a PR that changes app JS with the same native fingerprint as a prior BS dual build
    And reuse_main_builds is false
    When the Build Android Dual Versions workflow runs
    Then resolve-fingerprint-reuse reports found=true
    And build-with-srp and build-without-srp are skipped
    And Upload APKs to BrowserStack runs on Cirrus, repacks both profiles, then uploads
    And upload summary shows fingerprint-reuse-repack-<sha>

  Scenario: fingerprint miss still builds fresh
    Given no prior matching android-apk-main-e2e-bs-* artifacts for this fingerprint
    When the Build Android Dual Versions workflow runs
    Then both with-SRP and without-SRP Android builds run fresh
    And APKs are uploaded to BrowserStack as before

  Scenario: test-only PR still prefers BrowserStack custom_id reuse
    Given a PR with only test file changes and main BrowserStack apps resolve
    When run-performance-e2e runs
    Then trigger-android-dual-versions is skipped
    And tests use the resolved main BrowserStack app URLs
```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

N/A — CI workflow-only change; no app UI. Evidence is Actions logs +
timings above.

### **Before**

Miss path on this PR
([30554890417](https://github.com/MetaMask/metamask-mobile/actions/runs/30554890417)):
dual Gradle builds ran (~18m each in parallel); resolve→upload wall
clock **~26m 32s**.

### **After**

Hit path on this PR
([30570425894](https://github.com/MetaMask/metamask-mobile/actions/runs/30570425894)):
Gradle skipped; `APK source: fingerprint reuse + JS repack`;
resolve→upload wall clock **~12m 27s** (~14m / ~53% savings).
Performance onboarding + imported-wallet tests passed on the repacked
apps.

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

- [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.

#### Performance checks (if applicable)

- [x] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

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

<div><a
href="https://cursor.com/agents/bc-83c6732f-f2f5-4168-92f3-c43d2033a60d"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-83c6732f-f2f5-4168-92f3-c43d2033a60d"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>



[MMQA-2147]:
https://consensyssoftware.atlassian.net/browse/MMQA-2147?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

---------

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

Wire interactive actions, sorting, and side filtering into the Perps Pro
market view positions/orders panel so traders can manage open positions
and orders without leaving Pro mode.

**Motivation:** The Pro positions panel previously rendered read-only
position and order cards. Figma specifies actionable controls,
sort/filter affordances, and a control row layout (sort settings → all
sides → ticker checkbox) that should reuse existing Perps flows.

**Solution:**
- Add `usePerpsProPositionsPanelActions` to centralize panel action
wiring with geo/eligibility gates, toasts, and bottom sheets.
- **Positions tab actions:** Enable Close, Reverse, and Share on each
position card; add editable TP/SL and isolated-margin rows (value text
and edit icon share one press target); wire **Close all** on the
aggregate unrealized P&L summary.
- **Orders tab:** Keep order cards read-only (no size/price/TP-SL edit
affordances); enable per-order **Cancel** only for cancelable synthetic
orders.
- **Sort:** Add a sort settings button that opens a **Sort by** sheet
(position value, unrealized P&L, funding rate). Default is position
value high to low; tapping the active option toggles high ↔ low before
Apply.
- **Side filter:** Add an **All sides** button that opens a **Filter
by** sheet (all types, long, short) with Apply; button label updates to
Long/Short when filtered.
- **Control row layout:** Sort settings icon on the left, All sides
button next to it, then the `$TICKER only` checkbox.
- Reuse existing navigation and sheets: close position, flip/reverse
confirm, close-all sheet, TP/SL screen with `usePerpsTPSLUpdate`, and
adjust-margin sheet for isolated positions.
- Add test IDs, locale strings, and unit tests for actions, sort, side
filter, and panel integration.

## **Changelog**

CHANGELOG entry: Added position and order actions, sorting, and side
filtering to the Perps Pro market view positions panel

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TAT-3596

## **Manual testing steps**

```gherkin
Feature: Perps Pro positions panel actions and filters

  Scenario: Close a position from the Pro market view
    Given I have an open Perps position and I am on the Pro market view Positions tab
    When I tap Close on a position card
    Then the close position flow opens for that position

  Scenario: Reverse a position from the Pro market view
    Given I have an open Perps position and I am on the Pro market view Positions tab
    When I tap Reverse on a position card
    Then the flip/reverse confirmation sheet is shown

  Scenario: Edit TP/SL by tapping the value or edit icon
    Given I have an open Perps position and I am on the Pro market view Positions tab
    When I tap the TP/SL value text or edit icon on a position card
    Then the TP/SL screen opens and saving updates the position

  Scenario: Edit margin on an isolated position
    Given I have an open isolated-margin Perps position and I am on the Pro market view Positions tab
    When I tap the margin value text or edit icon on a position card
    Then the adjust margin sheet opens with add/remove options

  Scenario: Sort positions by unrealized P&L
    Given I have multiple open Perps positions and I am on the Pro market view Positions tab
    When I tap the sort settings icon, select Unrealized P&L, and tap Apply
    Then positions are ordered by unrealized P&L high to low

  Scenario: Toggle sort direction for the active sort field
    Given the sort sheet is open with Position value selected
    When I tap Position value again and tap Apply
    Then positions are ordered by position value low to high

  Scenario: Filter positions to long only
    Given I have both long and short Perps positions and I am on the Pro market view Positions tab
    When I tap All sides, select Long, and tap Apply
    Then only long position cards are shown and the button label reads Long

  Scenario: Cancel an open order
    Given I have a cancelable open order and I am on the Pro market view Orders tab
    When I tap Cancel on an order card
    Then the order is cancelled and a success toast is shown

  Scenario: Close all positions
    Given I have one or more open Perps positions and I am on the Pro market view Positions tab
    When I tap Close all on the unrealized P&L summary
    Then the close-all positions sheet opens
```

## **Screenshots/Recordings**

N/A — UI changes are incremental (action buttons, editable rows,
sort/filter controls on existing cards). Manual verification on
iOS/Android simulator recommended.

### **Before**

### **After**


Positions and orders panel cards were read-only; Close all was
display-only; no sort or side filter controls.
<img width="1206" height="2622" alt="Simulator Screenshot - iPhone 17 -
2026-07-31 at 11 30 09"
src="https://github.com/user-attachments/assets/6d69ee52-2e31-4bb1-988d-8717d541f999"
/>
<img width="1206" height="2622" alt="Simulator Screenshot - iPhone 17 -
2026-07-31 at 11 30 06"
src="https://github.com/user-attachments/assets/22525be7-c521-4ed1-8e0d-16833efc1693"
/>
<img width="1206" height="2622" alt="Simulator Screenshot - iPhone 17 -
2026-07-31 at 11 30 02"
src="https://github.com/user-attachments/assets/e33018dc-b676-4736-bbce-6d9dd87d31db"
/>


https://github.com/user-attachments/assets/b09f932b-6b88-42c5-952c-7536b5587091



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

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **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 live trading paths (close, reverse, cancel, close-all, margin,
TP/SL) with compliance gating, but reuses established Perps flows rather
than new backend logic.
> 
> **Overview**
> The Pro market **positions/orders panel** is no longer read-only:
position cards get **Close**, **Reverse**, **Share**, tappable **TP/SL**
and **isolated margin** edits, and order cards get a working **Cancel**
(with all cancel buttons disabled while one cancel is in flight).
**Close all** on the aggregate P&L header is wired through the same
flows as the rest of Perps.
> 
> **`usePerpsProPositionsPanelActions`** centralizes navigation,
compliance/eligibility gates, toasts, and overlays (close-all, flip
confirm, adjust margin, geo block) via a
**`PerpsProPositionsModalPortal`** so sheets are not clipped by the
parent scroll view.
> 
> The Positions tab adds a control row: **sort** (position value,
unrealized P&L, funding rate from `usePerpsMarkets`), **long/short side
filter**, and the existing ticker-only checkbox. List order and summary
P&L respect the active filters; empty states cover side-only filters.
Order cards drop decorative edit icons; position row test IDs are keyed
by symbol only.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
11bbd9b. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Alejandro Garcia Anglada <aganglada@gmail.com>
#34134)

<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**

<!-- mms-check: type=text required=true -->

Fixes browser close/back navigation from Market Insights news articles
incorrectly landing on Explore.

1. **Reason:** Market Insights opened articles with `fromTrending: true`
only. `BrowserTab.handleClosePress` has special-case return flags
(`fromWhatsHappening`, `fromPerps`, etc.) and otherwise navigates to
Explore (`TRENDING_VIEW` / `TRENDING_FEED`). Swipe-right worked because
the native stack gesture correctly pops the browser screen.
2. **Solution:** Pass `fromMarketInsights: true` when opening the
browser from Market Insights, forward it through Browser → BrowserTab,
and handle it in `handleClosePress` with `navigation.goBack()` (same
pattern as What’s Happening).

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

CHANGELOG entry: Fixed browser back from Market Insights news returning
to Explore instead of Market Insights

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes: #34106

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Market Insights news browser back navigation

  Scenario: browser close button returns to Market Insights
    Given the user is on Market Insights
    When the user taps a news source
    And the article opens in the in-app browser
    And the user taps the browser close/back button (top-left ArrowLeft)
    Then the user returns to Market Insights
    And the user is not redirected to Explore

  Scenario: swipe right still returns to Market Insights
    Given the user opened a news article from Market Insights in the in-app browser
    When the user swipes right to go back
    Then the user returns to Market Insights
```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

### **Before**

Bug recording from
[#34106](#34106):
browser back from a Market Insights article lands on Explore.


https://github.com/user-attachments/assets/72293a69-f9e7-4130-b72d-f1816740b5f0

### **After**



https://github.com/user-attachments/assets/bbf5c1f6-d34f-405c-8da8-682d50e5236f



## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

- [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.

#### Performance checks (if applicable)

- [x] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

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

[Slack
Thread](https://consensys.slack.com/archives/C092MDPA0LU/p1785484726532229?thread_ts=1785484726.532229&cid=C092MDPA0LU)

<div><a
href="https://cursor.com/agents/bc-ee085fae-72ef-5177-bb6b-692a71336c45?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-ee085fae-72ef-5177-bb6b-692a71336c45&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

Migrates send confirmations to appium and removes the detox tests

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

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

<!-- mms-check: type=issue-link required=true -->

Fixes: https://consensyssoftware.atlassian.net/browse/MMQA-1990

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

NA

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

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

<!-- mms-check: type=checklist required=true -->

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [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.

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [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 E2E coverage for wallet send/confirm flows (including a real
on-chain submit in the native test) and CI sharding; production app code
is unchanged but regression signal for confirmations depends on these
tests.
> 
> **Overview**
> Moves **SmokeConfirmations** send coverage from Detox/smoke stubs into
**Playwright/Appium** specs under
`tests/smoke-appium/confirmations/send/`, and deletes the old
`tests/smoke/confirmations/send/*` files (including skipped BTC/SOL/TRX
placeholders).
> 
> The **native ETH** smoke now runs end-to-end on a local Anvil node:
login via `loginToAppPlaywright`, send MAX, confirm, assert
**Confirmed** on Activity, and validate the finalized tx hash in
metrics. The **USDC MAX** flow is rewritten the same way (Anvil +
Accounts API mocks, `currentDeviceDetails`) but still cancels on the
review screen.
> 
> **CI** splits `appium-confirmations-*-smoke` into **two parallel
shards** (`total_splits: 2`) on Android and iOS for the added runtime.
> 
> `RedesignedSendView.selectEthereumToken` now taps ETH by **asset test
ID** with the same **retry/until amount screen** behavior as ERC20,
replacing the Appium-only network-filter + text tap path.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
7b38127. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

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

Adds the TMCU-1209 Homepage Balance Breakdown experiment with two
treatment variants:

- **Icons:** category rows for Money, Tokens, Perpetuals, Predictions,
and DeFi with product-specific icons.
- **Allocation:** a proportional blue-to-slate allocation bar with
matching row indicators.

The treatment variants replace the legacy homepage balance header with a
shared portfolio hero and homepage-local breakdown. The aggregate:

- combines Money, token, Perps, Predict, and DeFi balances in the user's
display currency;
- computes allocation percentages from positive holdings while
preserving debt in the net total;
- combines token and trustworthy Perps baselines into the 24-hour
“Today” delta;
- distinguishes loading, partial-loading, error, ready, and ineligible
states without leaving the hero permanently loading;
- hides slices whose product feature flags are disabled and prevents
their queries, subscriptions, polling, cache invalidation, and
persistence work;
- consumes Predict live-position updates from the shared query cache
instead of opening a duplicate live-price subscription; and
- preserves the existing wallet-home onboarding fallback and routes
every visible row to its existing product destination.

The UI preserves privacy masking across the hero, rows, and allocation
bar; localizes percentages and Money APY values; supplies privacy-aware
accessibility labels and hints; and keeps the treatment hero aligned
with the existing transparent balance layout.

Wallet integration preserves control and unresolved assignments,
network/basic-functionality banners, growth content, discovery pills,
and action-button placement. Empty network banner containers are not
mounted, avoiding control and treatment spacing gaps.

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

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

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

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

CHANGELOG entry: Added a homepage portfolio balance breakdown
experiment.

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-1210
Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-1211

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Homepage balance breakdown experiment

  Scenario: Render the Icons variant
    Given a wallet with balances in supported portfolio categories
    And the Homepage Balance Breakdown experiment is assigned to "icons"
    When the user opens the Wallet homepage
    Then the aggregate balance is displayed above the category rows
    And Money, Tokens, Perpetuals, Predictions, and DeFi show the expected icons
    And tapping each visible row opens its existing destination

  Scenario: Render the Allocation variant
    Given a wallet with balances in supported portfolio categories
    And the Homepage Balance Breakdown experiment is assigned to "allocation"
    When the user opens the Wallet homepage
    Then the allocation bar uses the blue-to-slate category palette
    And category rows display matching colored dots
    And positive holdings determine the allocation proportions
    And DeFi debt reduces the aggregate net balance without producing a negative segment

  Scenario: Preserve privacy
    Given either treatment variant is active
    When the user enables privacy mode
    Then the aggregate balance, delta, row balances, and percentages are masked
    And the allocation bar is replaced by a neutral track
    And accessibility labels do not expose hidden financial values

  Scenario: Respect product availability
    Given either treatment variant is active
    And Money, Perpetuals, Predictions, or DeFi is disabled
    When the user opens the Wallet homepage
    Then the disabled product row is not displayed
    And the remaining eligible categories still contribute to the aggregate balance

  Scenario: Preserve banner spacing
    Given either the control or a treatment assignment is active
    And neither the basic-functionality banner nor network banner is visible
    When the user opens the Wallet homepage
    Then no empty banner space is reserved above the balance
    When a network or basic-functionality banner becomes visible
    Then the banner is displayed with the expected spacing

  Scenario: Preserve wallet-home onboarding
    Given either treatment variant is active
    And wallet-home post-onboarding is in progress
    When the user opens the Wallet homepage
    Then the existing account-group balance is displayed
    And the balance breakdown rows remain hidden until onboarding completes

  Scenario: Preserve the legacy homepage
    Given the experiment is assigned to "control" or has no active assignment
    When the user opens the Wallet homepage
    Then the existing account-group balance and homepage actions are displayed
    And no balance breakdown rows or allocation bar are mounted
```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

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

### **Before**

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

### **After**

<img width="378" height="558" alt="Screenshot 2026-07-30 at 12 24 02"
src="https://github.com/user-attachments/assets/b50711a1-a79b-4761-a1e4-1df61565f342"
/>
<img width="383" height="634" alt="Screenshot 2026-07-30 at 12 24 21"
src="https://github.com/user-attachments/assets/617febd8-d146-4e18-af62-7d3649d2f848"
/>
<img width="370" height="626" alt="Screenshot 2026-07-30 at 12 24 29"
src="https://github.com/user-attachments/assets/1748bbe1-fd0e-49f0-a3b0-1396a5370655"
/>

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

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [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.

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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**
> Large wallet-home surface area and new cross-product balance math
could misstate totals or deltas; mitigated by feature flags, extensive
tests, and `enabled` gates on background fetches.
>
> **Overview**
> Introduces the **TMCU-1209** homepage balance breakdown A/B test
(`control` / `icons` / `allocation`) and wires **Wallet** so treatment
arms replace the legacy `AccountGroupBalance` header with a new
aggregate hero plus category rows, while control and unresolved
assignments stay unchanged.
>
> A new **BalanceBreakdown** stack aggregates Money, tokens, Perps,
Predict, and DeFi into slice hooks and `useBalanceBreakdown` (totals,
allocation %, partial load/error hero state, and a combined 24h “Today”
delta from tokens + trustworthy Perps baselines).
**HomepageBalanceBreakdown** renders **icons** or **allocation** layouts
with privacy masking, Money APY, slice navigation, and `Balance
Breakdown Slice Tapped` analytics.
>
> Supporting changes add **`enabled`** (and related) flags on Money
balance, Predict portfolio, Perps live account, and connection polling
so aggregation can skip work when slices are ineligible; **Homepage**
lifts a single `PerpsConnectionProvider` with `isEnabled` tied to the
Perps flag; **NetworkConnectionBannerContent** is split out for banner
layout in treatment vs control.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
b1e4792. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- Generated with the help of the pr-description AI skill -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
runway-github Bot and others added 2 commits August 7, 2026 14:45
…l enabled when position price ticks (#34470)

chore(runway): cherry-pick fix(social-leaderboard): keep QuickBuy Sell enabled when position price ticks
@github-actions

This comment has been minimized.

runway-github Bot and others added 5 commits August 7, 2026 16:53
…gs copy and casing (#34491)

- fix(settings): update notifications settings copy and casing (#32922)

<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

Updates copy in the Notifications settings screen to match current
content guidelines. Section titles now use sentence case (e.g. "Wallet
activity" instead of "Wallet Activity"), the wallet activity description
no longer mentions rewards, and the "curated" typo in the trading
signals description is fixed. Related unit tests are updated to match
the new strings.

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

<!--
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 notification settings section titles and
descriptions

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Refs: content update — no linked issue

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Notifications settings copy

  Scenario: user views updated notification section labels
    Given the user has notifications enabled in Settings
    And the app language is set to English

    When user navigates to Settings > Notifications
    Then section titles display sentence case (e.g. "Wallet activity", "Trading activity", "Price alerts")
    And the wallet activity description reads "Buy, sells, transfers, swaps"
    And the trading signals description reads "Updates from traders and assets you follow, plus curated market news"
```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

N/A — copy-only change with no visual layout differences.

### **Before**
<img width="408" height="216" alt="Screenshot 2026-07-07 at 4 53 57 PM"

src="https://github.com/user-attachments/assets/d48bee52-0dfa-4d4d-9ff5-241521e13f01"
/>
<img width="398" height="339" alt="Screenshot 2026-07-07 at 4 53 52 PM"

src="https://github.com/user-attachments/assets/4fa5782e-fe07-453b-a71b-aa6e7bbf451f"
/>
<img width="421" height="833" alt="Screenshot 2026-07-07 at 4 53 46 PM"

src="https://github.com/user-attachments/assets/00f46231-d6f1-4a17-b806-5424777a33c6"
/>
<img width="426" height="819" alt="Screenshot 2026-07-07 at 4 53 42 PM"

src="https://github.com/user-attachments/assets/7529597a-0003-4601-94b0-e6f9a7bb42af"
/>

### **After**
<img width="416" height="832" alt="Screenshot 2026-07-07 at 4 40 38 PM"

src="https://github.com/user-attachments/assets/2e759492-6fd0-4eb8-beb1-21a6dbeb1d19"
/>
<img width="418" height="827" alt="Screenshot 2026-07-07 at 4 40 32 PM"

src="https://github.com/user-attachments/assets/05b8ee5a-b2f3-4e58-ad6c-281a4b122a78"
/>
<img width="419" height="835" alt="Screenshot 2026-07-07 at 4 40 28 PM"

src="https://github.com/user-attachments/assets/a9f437c5-5a1e-4a4c-9e36-ed87038bf9c3"
/>
<img width="412" height="815" alt="Screenshot 2026-07-07 at 4 40 23 PM"

src="https://github.com/user-attachments/assets/feb72d6e-f1f7-42c4-aaaa-b203c2622d21"
/>


## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [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.

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user

SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and

[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance

Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

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

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

Co-authored-by: Andrew Cohen <andrew.cohen@consensys.net>
… Pro fees layout (#34489)

- fix(perps): fix truncated market names and Pro fees layout cp-8.7.0
(#34476)

<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->

## **Description**

Long ETF and equity market names were overlapping the leverage badge and
price column in the market list, and the Pro market header title was
clipped too aggressively because it used a fixed `maxWidth`. The Pro
order summary fees row also cropped the VIP badge and used a different
text color than the other summary values.

This PR makes the market list title and header identity text shrink
around the leverage badge and right-side actions, removes the hardcoded
header name width, and adjusts the Pro fees summary row so the VIP badge
is fully visible and the fee value matches the other summary values.

## **Changelog**

CHANGELOG entry: Fixed truncated market names in Perps market lists and
headers, and improved Pro order summary fees layout.

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: Perps market layout truncation

  Scenario: market list shows long ETF names without overlapping price
    Given I am on the Perps Markets screen
    And I open the ETFs category
    When I view markets with long names such as "iShares MSCI South Korea ETF"
    Then the leverage badge stays within the row
    And the price column is not overlapped or clipped

  Scenario: Pro market header adapts to right-side actions
    Given I open a long-named market in Pro mode
    When the header shows wallet, favorite, and Pro toggle actions
    Then the market name truncates within the available center space
    And the leverage badge and chevron remain visible

  Scenario: Pro order summary fees row displays correctly
    Given I am on a Pro market order form with an active VIP fee discount
    When I view the order summary fees row
    Then the VIP badge is fully visible
    And the fee value uses the same color and weight as margin and liquidation values
```

## **Screenshots/Recordings**

### **Before**

| Scenario | Screenshot |
| --- | --- |
| Pro order summary fees row | - |
| Market list (long ETF names) | <img width="300" alt="Market list ETFs"

src="https://github.com/user-attachments/assets/7c735f0a-c676-4816-9c48-c6be0652f439"
/> |
| Pro market header | <img width="300" alt="Pro market header"

src="https://github.com/user-attachments/assets/bca8b008-9b1c-4955-891d-5c564c7e4d5d"
/> |

### **After**

| Scenario | Screenshot |
| --- | --- |
| Pro order summary fees row | <img width="300" alt="Pro order summary
fees row"

src="https://github.com/user-attachments/assets/ff6ac1a3-63aa-4318-be5c-acfa8e32e68d"
/> |
| Market list (long ETF names) | <img width="1206" height="2622"
alt="Simulator Screenshot - iPhone 17 - 2026-08-07 at 16 31 30"

src="https://github.com/user-attachments/assets/5ee0af4a-845f-4e65-bba7-ad58cc278dc2"
/> |
| Pro market header | <img width="1206" height="2622" alt="Simulator
Screenshot - iPhone 17 - 2026-08-07 at 16 31 34"

src="https://github.com/user-attachments/assets/0766d1ae-73be-445a-b251-070d523b79a2"
/> |

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

#### Performance checks (if applicable)

- [x] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user

SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and

[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance

Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

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

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

Co-authored-by: Cursor <cursoragent@cursor.com>
[82ae592](82ae592)

Co-authored-by: Alejandro Garcia Anglada <aganglada@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…ications (#34465)

- fix: hide foreground wallet_activity notifications (#34411)

<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

Follow-up to #34043. The previous `wallet_activity` filter in the JS
`onMessage` path was meant to suppress system banners only while the app
is open (so in-app transaction toasts remain the primary surface). In
practice it did not achieve cross-platform parity:

1. **Android**: filtering in JS could incorrectly affect delivery when
the app was backgrounded / not fully active, instead of only when the
app was in the foreground.
2. **iOS**: `AppDelegate.willPresent` always requested a banner via
`completionHandler([.banner, ...])`, so the OS still showed a foreground
banner regardless of the JS filter.

**Solution:**

- Gate the JS `wallet_activity` filter on `AppState.currentState ===
'active'` so suppression only applies in the true foreground; otherwise
return `true` and do not block this path.
- On iOS, suppress banner/sound/list for `notification_type ==
wallet_activity` in `willPresent` (badge only), while still forwarding
the message to Firebase for JS. Background / killed delivery is
unchanged (that path never hits `willPresent`).

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

CHANGELOG entry: Fixed wallet activity push notifications so they are
only hidden in the foreground and still appear when the app is
backgrounded or closed

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Refs: https://consensyssoftware.atlassian.net/browse/GE-357

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Hide wallet_activity push banners only while the app is in the foreground

  Scenario: Wallet activity while the app is open (iOS and Android)
    Given the user has push notifications allowed
    And the MetaMask app is in the foreground
    When a wallet_activity push notification is received
    Then the in-app transaction toast is shown for progress and completion
    And no wallet_activity system notification banner is displayed

  Scenario: Wallet activity while the app is backgrounded (iOS and Android)
    Given the user has push notifications allowed
    And the MetaMask app is in the background or closed
    When a wallet_activity push notification is received
    Then the OS still delivers the push notification normally

  Scenario: Non-wallet_activity push while the app is open
    Given the MetaMask app is in the foreground
    When a non-wallet_activity push notification is received (e.g. platform)
    Then the system notification banner is still displayed
```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

N/A

### **Before**

N/A

### **After**

N/A

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [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.

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user

SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and

[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance

Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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 cross-platform push presentation paths; wrong gating could
hide wallet activity alerts or duplicate them in foreground, but
behavior is covered by unit tests and aligns with existing toast UX.
> 
> **Overview**
> **`wallet_activity` push banners are now suppressed only while the app
is truly in the foreground**, so background/closed delivery still shows
OS notifications and in-app transaction toasts stay the primary surface
when open.
> 
> On **JS/Android**, `shouldDisplayForegroundPushNotification` now
returns `true` unless `AppState.currentState` is `active`, then applies
the existing `wallet_activity` filter—avoiding suppression when the app
is backgrounded or inactive. Tests mock `AppState` and cover foreground
vs `background`/`inactive`.
> 
> On **iOS**, `AppDelegate` `willPresent` still forwards to Firebase for
JS but, for `notification_type == wallet_activity`, completes with
**badge only** (no banner/sound/list) instead of always requesting a
foreground banner.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
a3f6506. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[75ed6ce](75ed6ce)

Co-authored-by: Baptiste Marchand <75846779+baptiste-marchand@users.noreply.github.com>
@github-actions

This comment has been minimized.

runway-github Bot and others added 2 commits August 7, 2026 21:29
…34485)

- feat: add Pro only reduce only validation cp-8.7.0 (#34381)

<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

<!--
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?
-->
Reason for the change: Perps Pro users could hit confusing or blocking
errors when using Reduce Only — including cases where Place Order failed
without clear guidance, TP/SL stayed visible/active when it should not,
and validation banners looked misaligned when messages wrapped to
multiple lines.

Improvement/solution: This PR adds Pro-only reduce-only validation that
runs before submission, shows the TAT-3255 banner copy, disables Place
Order for invalid states, hides/clears TP/SL while reduce-only is on,
and starts the size input empty. Validation banner icons are vertically
centered with the message text for better readability on wrapped copy.

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

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

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

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

CHANGELOG entry: Fixed Perps Pro Reduce Only validation so invalid
orders show clear warnings before submission, and improved validation
banner layout.

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes: https://consensyssoftware.atlassian.net/browse/TAT-3648 and
https://consensyssoftware.atlassian.net/browse/TAT-3678

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Perps Pro Reduce Only validation and banner layout

  Scenario: Reduce only with no open position shows banner and disables Place Order
    Given I am on the Perps Pro market view for a market where I have no position
    When I enable "Reduce only"
    Then I should see a warning banner about having no position to reduce
    And the "Place order" button should be disabled
    And the TP/SL row should be hidden

  Scenario: Reduce only on the wrong side shows banner and disables Place Order
    Given I am on the Perps Pro market view with an open long position
    When I select "Short" and enable "Reduce only"
    Then I should see a warning banner that reduce only must match my position side
    And the "Place order" button should be disabled
    And the TP/SL row should be hidden

  Scenario: Reduce only size larger than closable position shows centered warning banner
    Given I am on the Perps Pro market view with an open position
    And I have enabled "Reduce only"
    When I enter a size larger than my closable position
    Then I should see a warning banner that the reduce only order is too large
    And the warning icon should be vertically centered with the banner text
    And the "Place order" button should be disabled

  Scenario: Valid reduce only order can be submitted
    Given I am on the Perps Pro market view with an open position
    When I enable "Reduce only" on the matching side
    And I enter a valid size within my closable position
    Then I should not see a reduce only validation banner
    And the "Place order" button should be enabled

  Scenario: TP/SL is hidden and not submitted while reduce only is on
    Given I am on the Perps Pro market view
    When I configure TP/SL and then enable "Reduce only"
    Then the TP/SL row should be hidden
    And submitting an order should not include TP/SL values

  Scenario: Limit order clears TP/SL after successful submission
    Given I am on the Perps Pro market view with a limit order form
    When I configure TP/SL and successfully place a limit order
    Then the TP/SL checkbox should reset to unchecked
```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

<!-- 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/87b3612d-6035-43bb-afa6-d332afa29d3f




https://github.com/user-attachments/assets/3e86973b-2fc9-48d8-a058-20ecb2288d7e




https://github.com/user-attachments/assets/7a555e65-def8-4b01-aca6-f613723d9b76


## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [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.

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user

SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and

[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance

Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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 order submission and validation on the Pro trading path
(reduce-only, TP/SL stripping, minimum-notional exemption); well tested
but incorrect logic could block valid closes or allow invalid orders.
> 
> **Overview**
> **Perps Pro Reduce Only** now validates against the live position
before submit: no position, wrong side (same direction as the open leg),
or size larger than the position each show a warning banner, disable
**Place order**, and hide the TP/SL row.
> 
> Enabling Reduce Only **clears TP/SL** in form state; submitted orders
**omit TP/SL** even if stale values remained. New
`validateReduceOnlyOrder` drives notices and `isFullClose`; full closes
skip the UI minimum-notional check and pass `reduceOnly` / `isFullClose`
through to protocol validation. Margin and limit-price errors surface as
**banners**; validation is skipped while the position stream loads to
avoid stale errors.
> 
> The Pro form replaces the Reduce Only checkbox with row-style
**selection indicators** (shared with TP/SL), centers banner alert
icons, and adds i18n strings for the three reduce-only messages.
Coverage spans hook, form, view, and util tests.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
57b625d. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[d6ae2b1](d6ae2b1)

Co-authored-by: Matt D. <85914066+geositta@users.noreply.github.com>
@github-actions

This comment has been minimized.

metamask-ci Bot and others added 2 commits August 7, 2026 17:01
This PR updates the change log for 8.7.0. (Hotfix - no test plan generated.)
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

🚀 RC Builds Ready for Testing

Platform Link Version
iOS TestFlight Go to TestFlight and download build 6409
Android Download from CI RC 8.7.0 (6409) — download APK artifact from the linked run
More Info
  • Version: 8.7.0
  • iOS Build Number: 6409
  • Android Build Number: 6409
  • Build Pipeline: View Pipeline

🛡️ Build Environment

Setting Value
Environment rc
Build Type main
Remote Feature Flag Env rc
Remote Feature Flag Distribution main
Ramps Environment production
API URLs & Details
API URL
Rewards API https://rewards.api.cx.metamask.io
Portfolio API https://portfolio.api.cx.metamask.io
Portfolio API (alt) https://portfolio.api.cx.metamask.io
Security Alerts API https://security-alerts.api.cx.metamask.io

Build Flags:

  • Build Name: main-rc
  • HAS_TEST_OVERRIDES: false
  • RAMP_DEV_BUILD: false
---

🍒 What's in this RC

Cherry-picks (6 commits)
Commit Description
e82aa46efb release: release-changelog/8.7.0 (#34443)
824b2434c3 chore(runway): cherry-pick feat: add Pro only reduce only validation (#34485)
c0d10cf09d chore(runway): cherry-pick fix: hide foreground wallet_activity notifications (#34465)
bac0ad4a6c chore(runway): cherry-pick fix(perps): fix truncated market names and Pro fees layout (#34489)
c322747b84 chore(runway): cherry-pick fix(settings): update notifications settings copy and casing (#34491)
95866e1d7b chore(runway): cherry-pick fix(social-leaderboard): keep QuickBuy Sell enabled when position price ticks (#34470)

Changelog (823 commits from main at RC cut)
Commit Description
c179e48559 feat(perps): add Lite/Pro mode selection bottom sheet cp-8.7.0 (#34395)
f6f1daab36 fix(perps): polish Pro market UI and order form interactions cp-8.7.0 (#34398)
e3517ccd56 feat: move seedless Appium coverage to CV/unit (#34172)
cc8432d437 fix(activity): correct the Network row on MetaMask Pay funding activity (#34313)
c977ad516a fix(ci): re-check for a reusable Android build before starting the compile (#34401)
6c2388b128 fix(ci): stop E2E gating logic from invalidating the native fingerprint (#34309)
15be657dd8 fix(ci): stop .gitignore edits from invalidating every cached native build (#34345)
85d96b793a chore: upgrade design system packages (v58.0.0) (#34430)
a8829c8bbc chore: remove unmountOnBlur option (#34363)
c10041bc77 feat: MUSD-1256 Update money deposit footer CTA button padding on token details page (#34380)
85d5c92136 fix(activity): replace "Swap again" with "Lend again" on lending activity details (#34310)
4a7825c97c fix(activity): restore the block-explorer sheet for cross-chain bridges cp-8.7.0 (#34373)
4fdb11e657 fix(ci): make artifact availability, not run completion, decide reusable-build donors (#34270)
0b21fe83bd fix(social): remove useElevatedSurface shim from Social & AI BottomSheets (TMCU-1050) (#33164)
4328148860 test(e2e): migrate confirmations transactions smokes to Appium (MMQA-2046) (#34338)
70d360faaa refactor(confirmations): migrate alert-modal buttons to MMDS Button (#34372)
e31f16ba70 fix(predict): keep PWAT auto-select on betslip reopen (#34371)
d530f7a239 fix: wallet activity notif settings first account toggle (#34247)
9c38522da9 fix(NetworkListBottomSheet): wrap FlashList in Box for better bottom sheet rendering (#34407)
acd6d5f05a refactor(confirmations): migrate BottomSheet components to MMDS (#34308)
f3ae029682 feat: Swaps CTA button AB test (#34306)
388e5edbec fix: update selectedSelectedInternalAccount to not capture exceptions where the selectedAccount is emtpy (#34301)
e95d2e86db chore: deprecate non-EVM pre-Unified Send Flow code (#34397)
d8911c8117 fix(appium): restore phase timing capture across Playwright use() (#34382)
128ed3637b feat(perps): add market filter toggle to Orders tab (#34351)
96ae46f447 fix: keep QuickBuy quick-amount K/M suffixes visible at large font sizes cp-8.6.0 (#34393)
f6a29a0c76 fix(perps): make Pro order book numbers readable at any price scale (#34330)
2d1c72a8fe refactor(ramps): move provider-compatibility switch to RampsController (#34195)
be84d92a84 feat(perps): update mobile to latest perps controller version (#34385)
a2a221bce9 fix: cp-8.6.0 Fix unintentional no_pay_token_quotes alert triggers (#34388)
5626d708c5 test: fix appium stale webview cdp cache (#34400)
c53f81139c fix(card): add cross-device guardrail that prevents a single money account from linking to two different metamask cards (#34294)
3909cf8339 fix(money): realign Money account header spacing with Home (MUSD-1245) (#34344)
158d891acf fix(perps): repair Pro order form keyboard and input issues (#34227)
09a8115c66 feat(ramps): instrument Buy E2E CUF with Sentry performance tracing (TRAM-3779) (#33873)
6ab2ede7b0 fix(money): adjust earnings tooltip sheet spacing, close button and body colour (MUSD-1244) (#34336)
9488fc9cea feat(agentic-cli): use push onboarding bottom sheet for CLI login nudge (#33699)
dedf813435 test: Migrate network abstraction E2E tests to appium (#34353)
4e9274152f fix(perps): correct mode-aware navigation and market switching (#34326)
756e897063 test(e2e): Android WebView CDP paths for tap, fill, read, select, blur (#34355)
c85973a40e test: skip Appium token approve smoke suites (#34387)
d42ec5997d feat: add somnia support (#34146)
1b9305d802 fix(perps): remove local env fallback for Pro mode feature flag (#34390)
756511f216 refactor(confirmations): migrate banners to MMDS BannerAlert (#34374)
cb85dc03cc fix: keep SRP backspace focus at end of previous word (#34383)
dd2f1d8e84 fix: show informative error for Ledger V3 typed data signing (#31677)
bd03cfad89 fix: cp-8.6.0 Fix re-selecting selected token in pay-with-modal (#34337)
a8e4256f72 test(appium): harden session reuse against soft-reload device failures (#34347)
8869f6824e test: skip Appium MMConnect multichain browser connect suite (#34354)
2046e6a4aa fix(activity): align perps filter labels and pluralize the Orders bucket (#34311)
b568871ba0 ci: gate expo dev builds on native fingerprint changes (#34249)
308df1f580 fix(ci): use cherry-pick version from PR title for release labels (#34160)
1e84a54121 fix(predict): accept valid no-op payment routes (#34350)
ef054717eb perf: remove whole-state passthrough inputs from account token selectors (#34339)
bc3233b00e fix(perps): remove useElevatedSurface shim from Perps BottomSheets (TMCU-1040) (#34312)
92d334a836 fix: clear Transak token on wallet setup (#31522)
035e30b57e feat(card): show Immersve region legal docs on SignUp and Card Home (#34220)
852346eee0 feat(appium): per-phase timing telemetry for smoke tests (#34335)
cfec3ee402 feat: gate scam questionnaire behind LaunchDarkly remote flag (#34297)
3828f7a024 fix(walletconnect): restore per-session channel id as the Snap request origin (#34284)
a64aa86357 fix: skip money account total insufficient alert on Max deposits cp-8.6.0 (#34360)
a692f4f65a feat: add Homepage search entrypoint, swap Explore tab icon, instrument search opens (#34296)
0dbe2334fa fix: stop MM Pay Max from stranding Loading on dust or unchanged amount (#34117)
5ba24a9495 feat(predict): add Trade Completed analytics event (#34218)
b0be128c71 fix: MMQA-remove-system-tags-from-performance (#34341)
7374ec2d31 feat: mirror token watchlist add/remove to Price Alerts (#34343)
b4d369a357 feat: bump defi v2 controller (#34265)
4dbe117dc8 fix: skip gas sponsorship reserve warning for MM Pay transactions cp-8.6.0 (#34352)
84dbf63c0d test: Migrate network expansion E2E tests to Appium (#34199)
c65cefad45 feat(perps): Pro open-order price and size edit (#34342)
7e5c07e9aa test(appium): stabilize multi-SRP account list and Snap OK alert dismissal (#34317)
e70fe740c5 fix(walletconnect): match WC metadata to permission origin on connect screen (#33308)
e8fa218ce9 refactor(perps): unify market headers and slide-up market list (#34282)
29ede59ec7 fix: merge foreign EIP-7702 auths in Gas Station publish hook cp-8.6.0 (#34210)
e004618524 feat: add QuickNode failover URLs for zkSync Era and MegaETH (#34215)
4a61f759ab feat(perps): add order edit trading and stream foundations (#34323)
e98bb9775f fix: apply Max path for money account deposit prefills cp-8.6.0 (#34327)
0d123d05ae chore: track asset_id on token watchlisted (#34262)
80e0c1e602 fix: TSA-971 filter sheet last option hidden by the Android nav bar cp-8.6.0 (#34285)
0d3113d7fb fix(login): end Login User Interaction on biometric unlock (#33960)
1cc15e4e49 fix(assets): remove useElevatedSurface shim from Assets MMDS BottomSheets (#33167)
ce6aa5e242 chore(assets): memoize PriceChartContext provider value (#34318)
a5df6a25b2 test(e2e): migrate token-approve confirmations to Appium (MMQA-2189) (#34293)
b3c38c0469 fix(snaps): Ensure fontWeight is properly inherited (#34319)
df8b73def3 fix: TSA-969 header layout shift on What's Happening detail view (#34260)
229f2d912c test: fixing seedless performance tests (#34200)
6aa19e4fbd fix: update Agent CLI QR login copy (#34174)
61d6e3afbd fix(confirmations): remove redundant useElevatedSurface from MMDS BottomSheets (TMCU-1044) (#33166)
df8985da39 fix(TMCU-1046): remove useElevatedSurface shim from onboarding BottomSheets (#33161)
727a2cdb1a feat(predict): add Trade Considered analytics event (#34217)
05fd4b7e64 fix(perps): prevent invalid asset errors after device lock (#34256)
a6472517ba chore(stellar): stellar preparation PR - 2 (#34233)
3f41326762 chore: New Crowdin Translations by GitHub Action cp-8.6.0 (#34020)
056ac5aaed chore(navigation): declare modal presentation for RootModalFlow and Confirm (#34161)
fa9363f332 feat: add SRP tagging at login time (#34300)
817b1a88ef fix(TMCU-1045): Remove useElevatedSurface shim from Core UX bottom sheets (#33162)
83ca9f12c4 chore(navigation): de-brittle native-stack test mocks for v7 prep (#34159)
33392eff34 fix(activity): show swap and bridge activity correctly on token detail pages (#34224)
643bcb2542 chore: performance tests refactor (#34163)
de179f5a94 feat: consolidate scam questionnaire analytics events (#34219)
0aa5ae3424 refactor(perps): migrate leverage bottom sheet to MMDS slider layout (#34094)
6bdff52dde fix: patch smart-transactions-controller to add the tx-sentinel robinhood URL cp-8.6.0 (#34295)
f7bc233810 fix(perps): correct Pro copy for size label, order pills, and side filter (#34267)
39bec91ed1 feat: add defi controller v2 flag to homepage (#34288)
77785f8bc3 chore: remove unused failing workflow (#34275)
aef49db783 ci: add extra shard for cv test (#34239)
9c4db58e3e chore(navigation): land v6-safe prep for React Navigation 7 (phase 1) (#34156)
af5853762f chore(ramp): adopt core-owned Headless Buy default redirect URL (#34207)
2c3f5da107 fix: swap ARC prevent native pre-select (#32212)
68f4d4c316 fix: deep links foreground notifications (#33662)
175b2cb880 fix: Refine right transition animation to improve perceived performance (#34234)
5d35d85b40 refactor(perps): migrate Adjust Margin to MMDS Slider and HelpText (#34093)
5929b3529a perf(add-asset): virtualize the AddAsset network list bottom sheet (#34266)
d157a0d2f0 fix: TSA-970 header layout shift on Follow Trading screens cp-8.6.0 (#34278)
beba8bf820 fix(locales): replace ampersands with "and" in user-facing strings (#34157)
76d81ba710 fix(money): tilt the Money card on both axes with card_tilt_v1.4 (MUSD-1201) (#34259)
060d0b38f8 test: assert Whats New Link Clicked feature and action props (#34214)
001906cbe6 refactor(confirmations): migrate staking and TemplateRenderer Text to MMDS (#34230)
a9ee088570 feat(perps): move market About section below Stats cp-8.6.0 (#34252)
f931cf3931 chore(core-platform): remove unreachable dead code (#34034)
3a5a4b3d49 fix: pressing on swaps search result not selecting token (#34212)
d9475c6bea chore(e2e): remove TestHelpers debt + split WalletView (MMQA-2173) (#34251)
20bbba06f3 fix: unblock Money Account rows while quotes load (#34244)
6a4593f15a feat: defi positions v2 controller (#33488)
f525a7e452 fix: support Perps withdrawals for externally delegated accounts (#34250)
a050a94127 feat(confirmations): block MM Pay CTAs until pay amount lands (#33983)
2e2a74713a chore(earn): remove unreachable dead code (#34030)
9aaa20521b fix(money): open support from the Money kebab menu without dismissing the sheet first (MUSD-1242) (#34248)
f0b7e0858c fix(perps): fill limit price on Pro order book row tap (#34202)
0eeac7e45e chore(assets): stable FlashList keys in ConfirmAddAsset (#34238)
52bf22dca3 fix: Monad send native reduced amount ux glitch (#34150)
1d20f11be9 test: reduce Predict unit/CV overlap (MMQA-2104) (#34197)
5e77eb467a test: fix predict flaky cv test (#34241)
0d5d4439fe release: Bump main version to 8.7.0 (#34242)
67486d2b32 chore(e2e): Appium docs SSOT + ban new UnifiedGestures imports (#34237)
45de2295df test: multichain tests Appium migration (#34151)
53a3ca51ef test(e2e): Android WebView CDP scroll for Appium snaps (#34235)
1bb13fe988 feat: enable max-amount withdraw to Money Account vault via post-Relay deposit (#33489)
269c72608f test(e2e): migrate remaining Perps Detox smokes to Appium (#34201)
8dead5a3cf feat(perps): switch market when tapping a Pro positions/orders row (#34181)
a39af59a79 refactor(react-compiler issue): migrate ImportFromSecretRecoveryPhrase to TypeScript (#33812)
9d5ca905b8 fix(sentry): use a single clock domain for span start and end times (#33694)
a7847f8bf7 fix: apply top safe-area inset to Add Device back button on iOS (#34185)
4f6fb349e4 chore(confirmations): remove unreachable dead code and unused barrels (#34033)
bbd9ec940a fix: fail fast in set-secrets-from-config.js when ALL_SECRETS is missing (#34222)
7e62a68b31 perf(useTokenLogo): stabilize default Set params and memoize handlers (#34105)
c767daf45a refactor(card): remove Immersve program-ID selector and temporary override (#34141)
a05fe09921 chore: bump @metamask/phishing-controller to 17.3.1 (#34158)
4b8732a3d9 ci: exclude Android native build intermediates from E2E yarn cache (#34051)
46d1eff412 chore(predict): remove world cup related files and components (#33625)
3aa4425e4d fix(bridge): restore hardware wallet post-trade modal after swap (#33865)
53b3b1ed0c test(e2e): migrate JSX + Multichain Provider Snap smokes to Appium (#34126)
fe4deaf73d fix(perps): route funding Track to redesigned activity details and show Pay fees (#34085)
beb4ebac1b fix(perf): prefer fresh BrowserStack APK URLs (#34211)
6f1fab5aff fix: round down money account Max/withdraw amounts past balance cp-8.6.0 (#34196)
72da947d9b feat(perf): track RC performance results in Sentry and Slack (observe-only) (#34009)
7521a285bb fix(predict): block duplicate order submission during in-flight placement (#33079)
61245b12ae fix(ci): pass test-source-prefix for Appium Playwright health report (MMQA-2013) (#34188)
5a5bb05156 fix(card): defer home data fetch and fix Money loading flash (#34021)
ccb432a5b9 feat(onboarding): skip checklist Notifications step after the OS push request (#34086)
330651e8a1 feat(analytics): fire App Opened on cold start with type and source props (#33669)
6c348c9e87 feat: add visual test agent (#33858)
d8a74539c8 fix(card): hide change asset on card dashboard when money account is linked (#34187)
9e6a9dd2c3 test(e2e): remove unused Detox smoke performance suite (#34183)
7555702509 test: migrate api-specs from Detox to Appium (MMQA-1988) (#34119)
fcd4b890fb feat: prefetch Money Account deposit quotes while typing (#33512)
fdb1979d59 test(e2e): migrate Interactive UI Snap smoke to Appium (#34169)
8b44ec0be1 test(e2e): migrate BIP-44 Snap smoke to Appium (#34103)
98587ce082 test(e2e): migrate Snap Management smoke to Appium (#34128)
5884d18be0 ci(e2e): run Appium iOS on PRs that change smoke-appium (#34164)
78e40265be test(e2e): migrate BIP-32 Snap smoke to Appium (#34102)
b42b349a03 chore: revert add @metamaskbot create-testflight-build PR command (#34177)
597f88ac9e test(e2e): migrate Preinstalled Snap smoke to Appium (#34132)
4dac5cf7c0 test(e2e): migrate Name Lookup Snap smoke to Appium (#34130)
7cd818f2f3 test(e2e): migrate Manage State Snap smoke to Appium (#34127)
e9c5bd32e2 test(e2e): migrate Get Entropy Snap smoke to Appium (#34122)
2d40b62fa8 test(e2e): migrate Ethereum Provider Snap smoke to Appium (#34121)
920629a885 feat(ci): add @metamaskbot create-testflight-build-{exp,rc} PR command (#34136)
07a78abfd8 test(appium): session reuse + soft reload and smoke shard rebalance (#34166)
06d0978a3b fix(stellar): XLM spendable balance with mask when privacy mode is on (#34171)
5b0ba413c5 fix(agentic-cli): abort CLI wait when Mobile cancels QR login (#33964)
ee7fac8435 fix: MUSD-1240 [Bug] Money Home "7% APY" text cut off on Google Pixel devices cp-8.6.0 (#34167)
9ddf0a3434 fix(browser): keep dapps in-app via WebView source.uri (#33879)
d6f718710e test(e2e): stop forcing native context in Appium Assertions (#34165)
76e46de928 test(e2e): migrate Dialog Snap smoke to Appium (#34120)
d16b6f6b45 test(e2e): migrate Network Access Snap smoke to Appium (#34131)
df8adc8f25 feat(money): add device-tilt parallax to Money card thumbnails (MUSD-1201) (#33808)
2b8c99538c chore: bump snap-account-service (report migration error) cp-8.6.0 (#34074)
b6c1f975b6 feat(metamask-pay): track quote errors in transaction events (#33332)
7c0d60c5b4 fix: report the real network name in Blockaid false-positive reports (#34078)
9b2ba6bf71 test(e2e): migrate Get File Snap smoke to Appium (#34123)
2b98e961f4 test(e2e): migrate Image Snap smoke to Appium (#34124)
6509733353 feat(predict): make sports feed filters follow active tab cp-8.6.0 (#33714)
a92a78a790 test: MMQA - 2026 - [Mobile] Remove anti-patterns from performance/mm-connect/utils.ts (#33969)
d4875f93b8 chore(navbar): remove un-used navbar functions (#34087)
dbad661bb8 feat: add homepage balance breakdown experiment (#33981)
a16ab5d315 test: migrate confirmation send tests to appium (#34069)
7b83cbf0ea fix: browser back from Market Insights news returns to Market Insights (#34134)
faaf120aca feat(perps): wire Pro positions panel actions and filters (#34112)
7e6129a305 feat(ci): reuse fingerprint + JS repack for performance BS builds (MMQA-2147) (#34049)
3c3df929b3 feat: show CDN fallback for gas fee token icons (CONF-1739) (#34040)
55373dce90 test(e2e): restore serial session reuse for collapsed Snap Appium suites (#34104)
cde69d0689 fix: TSA-962 skip top traders fetch while wallet is locked cp-8.6.0 (#34107)
6bf386be71 refactor(pay): extract custom-amount inline components (#34092)
d21fe1b55d test(e2e): migrate Background Events Snap smoke to Appium (#34101)
949640ab4f fix(perps): polish Pro trading layout and available balance (#34115)
8b1c03afc0 feat(money): add moneyAccountBalanceSource to the feature-flag registry with production default rpc (#34068)
030600b5e4 refactor: cp-8.6.0 split getMetaMaskPayProperties into focused property helpers (#34111)
7c1237aa5d feat(confirmations): show metamask pay quote errors in alert (#32932)
ea168fbb1b feat: integrate money account utils (#33849)
37b7180910 feat(perps): add About section on Lite market details (#33999)
0ad007437b chore: removes quickbuy keyboard abtest and feature flag cp-8.6.0 (#34073)
2f7c0a42d2 chore: wire stellar asset component with stellar asset selector (#34048)
18737cb1df fix(assets): memoize selectTokensByAddress for referential stability (#34037)
48a7fbf6a0 feat(perps): wire Pro order form to state and submission (#33950)
1aa13f3f2c fix(assets): stable FlashList keys in SearchTokenResults (#33814)
c0e74dacbb test(e2e): migrate wallet/ smoke specs to Appium (MMQA-2006) (#34077)
d4b2aedd3b feat(tooling): integrate daily anonymizer for usage metrics collection (#32387)
055385907d feat: initialise new defi controller (#34000)
7d31fad3e1 feat: MUSD-1229 Update money-acount-balance-service cp-8.6.0 (#34084)
9f2c44efe4 feat(perps): add account bottom sheet and polish Pro market view (#34081)
e14b6b5d82 perf: memoize PriceChart priceList map out of render body (#33895)
79d4f44d15 fix(predict): route funding Track to redesigned activity details and show Pay fees cp-8.6.0 (#34026)
0b058b1dbe feat(wallet): hide the Money card while the onboarding checklist shows cp-8.6.0 (#34029)
7d8ae2205b feat(predict): expand extended sports leagues cp-8.6.0 (#33943)
ec5177a2bd chore: skip expo-dev artifact download when Actions digest matches (#34079)
e5bdac8d8d feat: MUSD-1212 implement new cta on token details page for stablecoins money account deposits (#34022)
9726b43576 feat(TSA-945): new feed (#34047)
ff9bd4561c feat(predict): add feed carousel remote configuration (#33875)
0f986d705e refactor: migrate what's happening cards to MMDS (#33958)
8982e5ed63 chore(predict): Add esports markets and dynamic game tabs to Predict (#34006)
9c50bb5af4 refactor(perps): migrate Close Position to MMDS Slider and HelpText (#33952)
20ff41d21d feat: add persisted collapse/expand to the Pro chart (#33888)
693a23ad3f feat: adopt optimized Money Account deposit quote pipeline (#33433)
ced32debe9 feat: use snap keyring v2/v1 split (#33580)
07c037a055 fix: remove Android duplicated push notification icon GE-392 (#34065)
4c6b75bd9c refactor(ci): rename changed_files to changed_spec_files (#33922)
5f03a92009 fix(perps): never land on Perps Home while Pro mode is active (#34052)
957031cf2d test(e2e): strengthen Appium Snap helpers ahead of remaining migrations (#34054)
02ef2a4e9c feat: quickbuy bottom sheet redesign (#34015)
ce3d5bb5e1 feat: filter out wallet_activity foreground push notifications (#34043)
f85530e4df test(perf): harden cloud Appium waits and performance selectors (#34008)
99313f9ba3 fix: use unified import path and return to tokens full view (#34039)
0d79030a00 fix(perps): memoize homepage sparkline hook result (#34059)
936f3f4dd8 feat: MUSD-1220 (Copy Changes Only) Improve Stablecoin & Token Detail Page CTA Flow to Route Users into Money Onboarding / Add Funds (#34023)
adc9c97c2c feat(perps): implement Pro mode market detail header (#33899)
9bb0b8a3bd fix(mm-pay): persist mm_pay_strategy for transactions failed on startup (#34038)
e57db03ff5 feat: add favorite when an alert is created (#33965)
93dbb69963 ci: limit Playwright health report Slack output to top 10 tests (#34050)
a0565aa2ec feat(onboarding): add onboarding.machine.ms and account_type to spans (#34017)
f20263c498 fix(perps): eliminate trade screen slider lag and flicker (#33590)
e715486cd5 fix(e2e): harden Appium Perps scroll and order readiness (MMQA-2141) (#34042)
13ca9de0ff perf(money): virtualize the potential earnings token list (MUSD-1231) (#33982)
52584b3d4f chore: update assets controllers for defi fix (#34010)
31ad013abe test: harden Appium SmokePredictions position scroll/tap (MMQA-2140) (#34001)
b23269d8fa feat(analytics): add Trader Feed Screen Viewed event (TSA-959) (#34036)
e512f8cf4a refactor(perps): use one-line sort options and tighten sort control padding (#33954)
8a930cf528 fix(perps): use one-line ListItemSelect for price grouping options (#33953)
82b686bf1c fix: show card transactions in the correct filter group (#33862)
95f3e1a597 refactor(confirmations): import hasTransactionType from @metamask/transaction-controller (#33830)
785a8504b7 test: migrate signature confirmations test to appium (#33528)
704772bf8d chore(navigation): point React Navigation's global RootParamList at the app's real RootStackParamList (Phase 5) (#33745)
a643200f94 ci(appium): unify seedless smoke tag and raise seedless/wallet shards (#34028)
ca5e81501f refactor(ramp): shared headless order-failed analytics builder + root overlay dismissal (#33711)
549aeead14 feat(perps): add live price and scrollable stats bar to Pro market view (#33846)
0db32f959f refactor(perps): migrate market detail banners to MMDS BannerAlert (#33883)
6302454793 test: MMQA - 2021 - [Mobile] Remove getTestElement functions from page objects SolanaTestDapp and BitcoinTestdapp (#33970)
a8df9d4f02 feat: add funding_amount_range to Wallet Setup Completed on SRP import (#33731)
ab708e1510 feat(rewards): surface VIP maintain-tier threshold on tier ladder (#33959)
c26d1147f6 chore(deps): bump rive-react-native to 9.8.5 (#33834)
2da1f8067b fix(ci): restore exec bit on hermesc and shell scripts in node_modules (#34004)
d16cf88f20 fix(social-leaderboard): skip QuickBuy quote fetch when a preset amount exceeds balance (#33994)
a2d145b23a fix: bump bridge controllers to prevent stale dest exchange rates cp-8.5.0 (#33955)
b9e0f853df chore: add physical iOS device install option to install:ios:dev (#32718)
e4dc380622 chore: New Crowdin Translations by GitHub Action cp-8.5.0 (#33682)
48789f74a3 fix: show Coinbase ramp orders in Activity when network is a name string cp-8.5.0 (#33976)
adcb0ead75 feat(swaps): add Robinhood Chain promo banner on swaps screen (#33985)
7ae496b877 fix(social-leaderboard): apply pressed state to entire Weekly Top Traders card (#33988)
f70430eefa fix: Polish Social AI toast for 8.6.0 release (#33773)
578fc4e86a chore: udpate the appium emulator api version (#33820)
5e07b97437 feat(money): add jwt based rate limiting support to money account api (#33978)
b5c05e743e refactor(selectors): replace direct state access with selector functions (#33789)
5c37a214c5 chore: update swap consumers to use and display partial QuoteMetadata (#33559)
288c803e87 feat: integrate unified balances and trace gating on mobile (#33967)
cafcab98ab fix: narrow EAS fingerprint CI sources to native-relevant workflows/scripts (#32941)
e729a23f10 test: add integration test for perps trade metric partially filled (#33998)
2cc4981ce2 refactor(predictions): update PredictionsSection to use new market slots structure (#33911)
72d0382f3c chore(STX): add Robinhood Chain to smart transactions supported networks (#33876)
a134943038 fix(ci): pass only changed spec files to avoid ARG_MAX crash (#33921)
e02b4ce1e9 feat(money): gate money home earning section behind feature flag (#33989)
d7c26c9f24 fix: harden Appium wallet-home readiness for SmokeAccounts (MMQA-2139) (#33968)
2c0d9a69dc feat(money): remove section arrows and footer CTA, simplify card section (MUSD-1219) (#33912)
89b59ff31c feat: add editable quick buy amount pills (#33779)
9363d18760 feat(ramp): consume JSON moneyHeadlessAllProviders payload + thread rampSurface into headless getQuotes (#33362)
b103a68645 feat(money): add smoothed tilt parallax to the First Deposit screen (MUSD-1204) (#33863)
7cefb5a432 feat(perf): auto-enable inline app profiling on failed PR performance tests (#33902)
0802d8d0e6 chore(e2e): remove unused Detox regression test suite and CI (#33893)
56259c373d chore: replace deprecated StyleSheet.absoluteFillObject with absoluteFill (component-library) (#33837)
316c1c05b5 feat(notifications): refresh Social API preferences cache after AUS write (#33856)
05b0c9ef12 fix: MM Pay Max button should not submit when there is no balance (#33957)
ddb183287f chore: memoize selectAllNftsFlat for referential stability (#33961)
3c669e4655 feat(onboarding): add screen and Rive Sentry performance telemetry (#33889)
3f77a811e9 test: ActivityScreen Predictions row component-view coverage (MMQA-2117) (#33934)
9d63b38782 feat: add UAT domain in bridge (#33829)
7eec3db4f1 ci: exclude Sonar binaries and raise JS heap to fix OOM (#33963)
96deb2a620 fix: Polish Money Movement toast for 8.6.0 release (#33769)
c1faefc4f1 chore: only fetch NFTs when section is focused and add skeletons (#33645)
b510d3a155 refactor: Updated Perps Limit Price BS to use MMDS (#33683)
6b016f47a5 feat: source GasFeeController and SeedlessOnboardingController from @metamask/wallet (#33430)
76c803a444 test: migrate SmokeBrowser specs to Appium 2/2 (MMQA-2092) (#33926)
2e849ad0f7 fix: Polish Card toast for 8.6.0 release (#33766)
0ae1981e3d refactor(perps): migrate Auto close TPSL view to MMDS (#33884)
d233a22015 chore: Bump skills repo to 0.2.0 (#33944)
a9e14a8960 fix: remove duplicated bottom inset on the Activity screen cp-8.5.0 (#33929)
4ed40bc16e revert: "feat: temporary 10-year anniversary app icon cp-8.5.0 (#33930)
caf4b9d01e perf(account-selector): cut list render churn and per-cell selector cost (#33877)
2591f031ca fix: Polish Mobile Core UX toast for 8.6.0 release (#33771)
32bf23f2d1 chore(money): opt in useNavigation to AppNavigationProp (Phase 4) (#33622)
2b15c42f9c fix: Polish Predict toast for 8.6.0 release (#33767)
80fcbb9e5a fix: route WalletConnect relay through built-in WebSocket (#33871)
08eb84a9cb fix: Polish Engagement toast for 8.6.0 release (#33772)
217619ef86 fix: Polish Web3Auth toast for 8.6.0 release (#33774)
3c4df5aa28 chore(navigation): opt remaining small teams into AppNavigationProp (phase 4) (#33678)
0de4ba0a7c fix: reduce Hyperliquid API calls on Token Details page from 6 to 2 (#33851)
bba77bcd23 fix(locales): use sentence case for Weekly top traders label (#33917)
a0519e49f5 test: reduce WalletActions and CancelAll unit/CV overlap (MMQA-2100) (#33793)
23d3a17247 fix(Engagement): handle stale Braze banners (#32412)
282d53b48e feat(migrations): add migration 148 to replace Infura IPFS gateway with default (#33908)
c2eb8c7eb5 test: ActivityScreen Transactions row component-view coverage (MMQA-2080) (#33894)
f9fe9248bd fix(ci): re-run PR size check on base retarget (#33868)
68f1f52dfa fix: Polish Earn toast for 8.6.0 release (#33775)
0b676a8425 fix: Polish Metamask Assets toast for 8.6.0 release (#33770)
82066407d9 refactor: remove A/B test HubPageDiscoveryTabs (#33652)
98cb4a82c9 test: stabilize SmokeStake lending seed and stake Confirm flow (#33910)
56408f89b8 chore(ci): standardize Detox and Appium test timeouts to 25m (#33891)
4ff57c8dff test(e2e): share Android WebView helpers via multi-platform WebView API (#33874)
21a20f887c feat(money): bind the live APY to the onboarding animation (MUSD-1206) (#33903)
e0cf57ef99 fix: remove default placeholder on price alerts cp-8.5.0 (#33904)
dd96bb416e fix: reject extraneous typed sign keys for V3/v4 messages (#33198)
5b08c05fbc fix: wire fallback history pagination into fullscreen chart (#33881)
21ae598f4c feat(ci): reuse main BrowserStack builds on manual performance dispatch (#33907)
4d8465970d fix(money): read vault config just-in-time and re-init on change (MUSD-951) (#33782)
a2e66a2408 refactor(confirmations): stage-based custom amount info (#33809)
20d74b3c7b refactor: flatten Import SRP step 0 spacing without gap/margin stacking (#33810)
0990e940d9 fix(sentry): discard timed-out onboarding traces instead of sending fake ~5-min durations (#33318)
ae7ad8b57f feat(money): wire up money account api interests endpoint requests + update UI (#33845)
d4e685e51f fix(perps): polyfill DecompressionStream for Hyperliquid fastAssetCtxs on Hermes (#33870)
e9142b4b78 feat: refactor non-zero native custom networks (#32796)
05fc1a602a feat: add createWidgetUrl functionality and proxy flag support for Transak service (#33777)
eecaed90da fix: remove duplicate staking API call on Ethereum Token Details page (#33854)
5324d4d9d9 fix: remove gap between symbol and price change on default token card watchlist cp-8.5.0 (#33859)
290d69f221 feat: make watchlist row draggable cp-8.5.0 (#33803)
2e7dbfb084 fix(agentic-cli): open settings on any Android deny after Turn on (#33744)
3070e21b1f test: migrate MMConnect e2e suite from performance BrowserStack to Appium smoke CI (#33380)
b3afe11012 fix(tests): harden ERC20 USDC selection in redesigned send E2E (#33890)
e483725c4e chore(testing): remove repository-owned integration skill (#33864)
554e947d39 refactor: use Arrow2UpRight for Send action buttons (#33878)
a3ca1a6492 fix: Add swipe to dismiss for DS Legacy toast (#33598)
9006438169 fix: Add swipe to dismiss for BaseNotification toast (#33600)
d3e2b96916 chore(multichain accounts): opt in useNavigation to AppNavigationProp (Phase 4) (#33627)
1eef0b193b feat: improve import-cancelled sheet UX for account sync failures (#33885)
ab10a0e7d4 test(onboarding): add Telegram seedless performance coverage (#33685)
4f60c2ef46 chore(web3auth): opt in useNavigation to AppNavigationProp (Phase 4) (#33676)
61888fa373 chore(confirmation): opt in useNavigation to AppNavigationProp (Phase 4) (#33558)
66a400defe test: add unit tests for usePerpsTrendingCarouselData hook (#33764)
85ab78e10f feat(swaps): add A/B-gated haptic feedback for swap interactions (#33732)
36b9b014f5 feat(perps): add pro positions and orders panel (#33755)
8b528c94a4 fix(tests): unskip lock alerts and harden en.json E2E selection (#33857)
dee32d386a test(e2e): migrate initial Detox snap smoke tests to Appium (#32877)
f211b52724 test: ActivityScreen empty-state component view coverage (MMQA-2079) (#33866)
b26d1cdbe4 feat: add Perps Pro chart panel (#33750)
84c1b200f2 feat: bump phishing controller 17.3.0 (#33756)
e81779780d feat(perps): block place order until the pay amount reaches the controller cp-8.5.0 (#33822)
ce22ad81fe fix(money): NBA module parallax reliability and inverted Y axis (MUSD-1203, MUSD-1202) (#33848)
8e365c1e7a test: add integration tests for Perps Trade Transaction Event executed (#33671)
957cfabac8 fix(pay): always emit mm_pay_payment_token_list_size on confirmation events (#33253)
8171bddb52 test(perf): Store app profiling result per scenario (MMQA-2081) (#33656)
973c6fc7fd feat(support): adopt support consent flow in RewardsVipRefereeView and LinkedOffDeviceAccountsSheet (#33520)
54e4635141 test: MMQA-2092 migrate wallet browser smoke to Appium 1/2 (#33816)
3e6183ad68 feat: detect OneKey accounts as hardware wallets (#33637)
75bc184ef2 feat(performance): add performance tests for Homepage, PopularTokensList, MultichainTransactionsView, and UnifiedTransactionsView (#33786)
db95e1d20a fix: perf(accessibility): fix iOS accessibility in Rewards components (#29127)
bb0fb36e4a fix(activity): cp-8.5.0 fix bottomsheet positioning when activity is a tab (#33794)
117ecd15a1 feat(rewards): wire First Predict On Us into onboarding (RWDS-1435 4/4) (#32860)
e1c0d590ff feat(Rewards): Update text of money card in Rewards banner carousel (#33804)
bed38cd2fa chore: delete multichain accounts feature flag (#33802)
498ac45419 feat: add prefill skeleton loader for money account deposits (#33707)
d3a7d5c257 refactor(predict): import hasTransactionType from @metamask/transaction-controller (#33833)
172699dd93 refactor(accounts): import hasTransactionType from @metamask/transaction-controller (#33831)
4df866555c test: MMQA-2091 migrate wallet analytics smoke to Appium (#33725)
e8c08ba007 fix(money): skip insufficient-funds alert on Max money account deposit (#33836)
22d49b924d refactor(perps): import hasTransactionType from @metamask/transaction-controller (#33832)
2fde612eb8 feat(support): adopt support consent flow in SRPErrorScreen and SocialLoginErrorSheet (#33523)
6b58a38f7a feat(support): adopt support consent flow in PerpsHomeView and service interruption banner (#33533)
923a9934f6 chore(assets-controller): bump to 11.2.1 (#33761)
3f9d0f227a refactor: refactor NetworkSelector component and enhance tests (#33768)
6b89300127 feat: wire QR metadata sync for existing-user accounts flow (#33696)
3b9ab7a143 fix: reorder TDP header icons cp-8.5.0 (#33819)
ab3b08b6ac feat(Stellar): add Stellar send flow support (#33563)
2ea6f465b2 feat(onboarding): enhance onboarding trace management and error handling (#32828)
ba0f19d022 fix(perps): correct CUF trace lifecycle and tags (#33562)
b36f96c6aa chore: bump notifee (#33415)
74e315622d refactor: simplify DOM in backup and social login screens (#33749)
a3e710999d fix(card): fix Immersve KYC spendableAmount and restore back header (#33790)
892058fa52 fix: dismiss SelectSRP sheet before reveal navigation (MMQA-2107) (#33806)
45c01abfa8 chore: upgrade MMDS to v56.0.0 (#33788)
5b554e662d chore(navigation): opt unowned surfaces into AppNavigationProp (Phase 4) (#33740)
7e06fbd5e3 chore(core): opt in useNavigation to AppNavigationProp (Phase 4) (#33666)
02ffa0dcee chore(assets): opt in useNavigation to AppNavigationProp (Phase 4) (#33628)
3e25578964 feat(component-library): remove bottom border from legacy BottomSheet by default (#33739)
eb376b7ac3 perf(predict): use stable sports market keys (#33476)
ca38156076 refactor: migrate formatters to @metamask/client-utils (#33733)
411c7924a9 feat: upgrade bridge controller packages (#33665)
e5c5ffe29e fix: restored old behavior to show Paid by MetaMask label in sponsored transactions from activity page cp-8.4.0 (#33778)
3b82b065fd feat: show slippage button on swaps screen before quote (#33797)
2f4dfef0aa feat(rewards): add First Predict On Us splash and order sheet UI (RWDS-1435 3/4) (#32859)
563d6bfb2e feat(support): adopt support consent flow in AccountsMenu and AppInformation (#33522)
c2be695868 fix: delegate RemoteFeatureFlagController for Accounts API balance v6 cp-8.5.0 (#33781)
6874ad173d fix(walletconnect): attach eip155 accounts when proposal mixes eip155 with adapter namespaces (#33672)
a2334a0410 fix: keep amount entry visible before quote loading (#33762)
6e9860fe61 refactor: present account screens as right-sliding cards (#33670)
b641a823a3 feat(predict): add remote feed banner (#33478)
b08bff8212 fix(assets): memoize selectAllTokensFlat for referential stability (#33753)
4258b72caf fix: broken pipeline price alerts (#33785)
028f1a11ff fix(money): show keyboard and resolve amount for fiat deposit flows cp-8.5.0 (#33780)
1d134429bb feat(support): adopt support consent flow in scam warning questionnaire (#33521)
36599014af chore: bump react-native-share to 12.3.1 and regenerate patch (#33602)
093b66b704 feat(card): resolve Immersve spendable balance from on-chain allowance (#33743)
83846dacb5 perf(predict): cut crypto up/down cpu in ws parsing and re-renders (#33757)
003f54f7c0 feat(support): adopt support consent flow in EligibilityFailedModal (#33519)
58ecae152f fix(money): guard parallax tilt dispatch against detached rive view (#33718)
9d9023599f feat(confirmations): add timing metrics to Transaction events (#33618)
4c8c49df4c chore: bump react-native-permissions to 5.6.0 (#33597)
fa5c998600 feat(support): adopt support consent flow in MoneyMoreSheet (#33518)
06c0d3ff9a ci: remove flaky FixtureValidation jobs from Appium smoke suites (#33776)
dd8a27f2b6 feat(money): play card flip animation on link card sheet (MUSD-1199) (#33704)
10e1671c9d chore: allow deprecating tokens controller through FF (#33570)
5c8642aba4 chore: remove price alerts FF (#33599)
f4eb563ea6 ci: pass AI analyzer gate for medium Runway cherry-picks into release branches (#33715)
4b9592af6f feat: add TransactionPayController sentinel messenger test (#33754)
2219d769d5 feat: improve Txn Detail Page (#33499)
28fef6bc1d feat(perps): add live order book to pro market view (#33664)
5897663c9e feat: split seedless Appium smoke into core and extended suites (#33751)
8a480513f1 chore(bridge): remove Batch Sell promo banner from source picker (#33742)
dd23cf82ee feat(ramps): point MM dev builds to ramps dev environment (#33686)
1fdf87e83c chore(navigation): opt unowned hooks into AppNavigationProp (Phase 4) (#33728)
db5f37e63d feat(card): polish Immersve onboarding and funding UX (#33655)
3adb1ca1fc feat(rewards): add VIP transactions list view (#33680)
11929342a7 feat: publish EIP-5792 capabilities in CAIP-25 session properties (WAPI-1560) (#32660)
7b338d02b1 fix(ramps): persist terminal analytics dedupe (TRAM-3769) (#33357)
83f9c39239 release: Bump main version to 8.6.0 (#33736)
534f6b4140 chore: adds Quick Buy numeric keypad vs slider A/B test (#33605)
5dc2cf650d test: MMQA-1992: Migrate smoke/fixtures Detox tests to Appium (#33507)
aa3cab8d60 test: MMQA-1991: Migrate smoke/deeplinks Detox tests to Appium (#33709)
76a29fa7df feat(support): add support consent flow core mechanism (#33424)
6ba5b090f0 feat: improve money account upgrade process cp-8.4.0 (#33427)
8d512234a7 chore(perps): opt in useNavigation to AppNavigationProp (Phase 4) (#33385)
531f925616 feat: bump transaction-pay-controller to 26.0.0 (#33719)
2fec7d955c feat(perps): add Pro order form UI (#33630)
3fb766b440 feat(agentic-cli): nudge push permission after CLI QR login (#33688)
72390ea48c fix: patch bridge controller to remove Stellar and Arc cp-8.4.0 (#33684)
934cc5d9cc chore: bump react-native-view-shot to 5.1.1 (#33603)
1b34461a29 feat: add watchlist drag and drop functionality (#33677)
e632dc202d refactor(Transactions): convert class component to functional component with hooks (#33578)
98a8cc9b35 refactor(homepage): remove trending sections A/B test and update related components (#33496)
c4cd940943 fix: show preparation state for Money Account deposits cp-8.4.0 (#33325)
32f25072ff feat: add item type extraction for list components (#33691)
c7db92788e fix(predict): route withdrawals by wallet type (#33551)
231f1a3739 chore: adds MarketCap to position cards in social Feed (#33706)
f54537a31e fix(money): show skeleton while money account resolves on home card (MUSD-1196) (#33698)
30133c23a5 fix: use text locator for Appium QR sync import-from-extension link (#33703)
fcfdbf94d8 chore: migrate assets-list selector to BigInt (ASSETS-3719) (#33700)
ba460487af chore: prefix token watchlist analytics event names (#33705)
4a135889ed feat(money): add instrumentation for money account api data service (#33701)
decd744d7a feat: support new notification services controller + segment schema (#31204)
b7e90803a3 chore: update watchlist instrumentation (#33675)
50d79e6070 chore: bump @metamask/tron-wallet-snap to ^1.33.1 (#33660)
c380719388 fix: skip calldata encoding for initial deposit batch creation (#33582)
9c7915495e fix: gate amount+fees balance check to money-account withdrawals only cp-8.4.0 (#33654)
4537ff26fa chore: bumps for assets-controllers and core-backend (#33651)
ac9b692bab chore(component-library): remove unused TextWithPrefixIcon component (#33511)
ddc5aba88c chore(component-library): remove unused SelectOption component (#33510)
dd593f4785 chore: migrate marketDetails and CollectibleOverview to BigInt (#33692)
2e66cef203 fix: label trader position CTA as Trade (#33697)
4c93620bc9 chore(component-library): remove unused SheetActions temp component (#33509)
c88ab64c7c feat(money): centralize money account balance fetching (#33516)
0a8b272a87 fix: monad assets not appearing in explore cp-8.4.0 (#33614)
14fc85f518 test: MMQA - 2025 - [Mobile] Remove antipatterns from helpers/multichain-accounts/common.ts file (#33571)
f8340eaf9b feat(perps): add reusable Lite/Pro mode toggle across entry points (#33572)
e269bfc937 refactor(perps): migrate Text and SensitiveText to MMDS (#33663)
5e87676cf1 feat: polish add-device / QR account sync UX. (#33564)
a2e70b85cf fix: skip failing tests (#33687)
d68e729c0b fix: transak native fallback for different env (#33553)
6ca0b48242 fix(bridge): tighten fiat/crypto toggle hit target (#33674)
5fdb70c757 test: Add MMC IAB tests (#31946)
647bf3b32f chore(swaps): graduate post-trade modal A/B test (#33626)
d73dde174e feat: add watchlist star to swap flow (#33566)
90dc66f6f1 chore: New Crowdin Translations by GitHub Action cp-8.4.0 (#33342)
f4af7a3a5c fix: remove approval text in swaps (#33668)
2c00f3e16c fix(ramps): resolve POL buy failure from token details page (TRAM-3713) (#33542)
49fc527619 test(onboarding): add fresh SRP wallet performance coverage (#33324)
e5cb9fb56f test(watchlist): add component view tests and framework support (#33609)
74dbb8d4aa chore(predict): opt in useNavigation to AppNavigationProp (Phase 4) (#33458)
cd436a6f5e chore(rewards): opt in useNavigation to AppNavigationProp (Phase 4) (#33453)
f47a66c98e perf(predict): memoize merged chart data (#33477)
cde83155f4 fix: Vertically center pressable Toast content (#33640)
20270b3f6a feat(perps): scaffold pro mode market layout (PerpsProMarketView) (#33560)
1d76e28d33 fix: Polish token contract copy toast icon styling (#33629)
34134361b3 chore: upgrade design system packages (v55.0.0) (#33653)
da9f3723ac refactor(perps): align PerpsPositionCard and PerpsCard with MMDS ListItem (#33552)
9c52b7e1f8 test: add component view and integration tests for tracking perps close poisition metric (#33647)
760a8028b8 fix(wallet): gate balance empty state on real refresh settlement (MUSD-1195) (#33589)
1d44eab738 chore: migrate deriveBalanceFromAssetMarketDetails to BigInt (ASSETS-3717) (#33644)
74385ec5e2 refactor: remove Cash section and update token filtering logic (#33638)
88493da3b2 perf(money): reduce Money Home and activity re-renders (MUSD-1205) (#33646)
6c4315643e style(locales): convert all-caps UI strings to sentence case (#26285)
809a08dbe0 refactor(perps): remove orphaned dead code modules (#33470)
4365f65136 feat(activity): add first-class RampsOrder support in Activity (#33624)
448e6915e7 chore: bump @metamask/tron-wallet-snap to ^1.33.0 (#33636)
3f4e3286c6 chore: remove AssetOverview Price files from util/number burndown (#33633)
e483210962 fix(perf): reflect quality gate failures in Slack category status (#33631)
0d7f7fa74f test: MMQA - 2024 - [Mobile] Remove unused methods in WalletView.ts (#33568)
de03ffcfd5 refactor: make ImportFromSecretRecoveryPhrase React Compiler compatible (#33503)
67089afe5f fix(agentic-cli): remove double top-inset on iOS AgenticCliDashboardWebview header (#33635)
4df245a3ab feat(Stellar): add Stellar related chain utils (#33480)
0313028d12 test: MMQA-2003: Migrate smoke/stake Detox tests to Appium (#33632)
7184677c4f fix: misalignment on copy button (#33591)
9d8f40a922 refactor: resolve React Compiler issues on Onboarding screen (#33482)
626583d902 refactor: make ImportNewSecretRecoveryPhrase React Compiler compatible (#33485)
fd2ec53cd5 fix: Polish perps toast for new animation (#32943)
801a438f35 refactor: merge new and recently added lists, add new pill to products (#33302)
745d8f806f chore: remove AB test for verified badge, permanently show verified b… (#33539)
8beb8007c5 refactor: Improve recently viewed ux (#33543)
30f61049cf Chore/use expo babel transformer (#33619)
04f6ce33a7 docs(Engagement): Update deeplinking doc callout (#33610)
d3b3fd4b75 feat(card): add Immersve UK SIWE auth re-entry (#33608)
4ad3bd0c21 chore: bump assets controller to v11.1.0 cp-8.3.1 (#33612)
084957e321 chore(bridge): opt in useNavigation to AppNavigationProp (Phase 4) (#33547)
c93c2a780e release: sync stable to main for version 8.3.0 (#33613)
f4950d896b feat: integrate STX failTransaction fix (bridge stuck-pending) (#33175)
d2ba1d5a69 feat(activity): clearer Activity swap & bridge row content (#33538)
df181160a5 feat(bridge): redesign bridge transaction details behind transactions-redesign flag cp-8.4.0 (#33471)
aff843fef5 perf(predict): memoize market feed items (#33475)
cc54d60ba4 chore(card): opt in useNavigation to AppNavigationProp(Phase 4) (#33441)
21e79b0964 test(perf): stabilize Appium performance metrics and flaky readiness probes (#33216)
86f07ca13f feat(activity): show account name and avatar for owned accounts in activity list (#33390)
f4a568e4fe feat: consume backend-suggested slippage in unified swap/bridge (#33431)
0c83bf18ae feat(confirmations): block hardware wallets for money account deposits (#32952)
c45035b316 refactor(perps): migrate Activity list and FillTag to MMDS (#33555)
f5b411671d refactor(perps): migrate market row to MMDS ListItem (#33554)
1b052812db refactor(perps): migrate HIP-3 debug view to MMDS components (#33452)
aa9ed4bbad fix: prevent deposit page auto-navigating to result page during editing (#33505)
2e628849ca fix(predict): stabilize parameterized selectors with weakMapMemoize (#33215)
ede6ab74fa fix: move watchlist section after predictions (#33601)
d01fed2e4d fix: Polish money toast for new animation (#32946)
78027390ce chore: remove world cup from explore (#33594)
14e36113cb fix: display 'Debit' instead of 'Debit or Credit' in MM Pay UI (#33513)
6024250fd6 feat(card): add Immersve CardHome read and sensitive details (#33557)
c583c2ebdd fix(predict): show net sell proceeds after fees cp-8.4.0 (#33449)
5af1095ded fix(money): rename "Money account benefits" heading to "Benefits" (MUSD-1197) (#33592)
c2fbf2d9c8 chore: remove backgrounds from money earn banner images cp-8.4.0 (#33584)
edf8031c3d fix(money): keep activity filter tabs stationary on selection (MUSD-1194) (#33586)
29dbcc511c feat: kick off money upgrade process in modal stack (#33587)
f3af5635aa feat(predict): add any-token withdraw Appium coverage (CONF-918) (#33490)
c8460abb03 chore: bump @react-native-community/slider to 5.2.0 (#33474)
9710d930e0 chore: bump react-native-safe-area-context to 5.8.0 (#33472)
e2826d16cb fix: Polish earn, quick-buy, rewards and gas toast for new animation (#32947)
68641eacfa fix(pay): auto-navigate to results page on Max press (#33532)
695dd604e3 chore: bump lottie-react-native to 7.3.8 (#33473)
232f642b07 fix: canonicalize typed-sign data to prevent display/signing divergence (#33187)
39f02f2058 feat(perps): show caret icon in market header clickable area cp-8.4.0 (#33495)
22d68a9327 chore: update black resources for Insights animation cp-8.4.0 (#33581)
64dfb41b19 revert: remove watchlist star filter from Trending Tokens (#33579)
aac38c85fc fix(money): prevent large balances overlapping Add button on Money card (MUSD-1183) (#33504)
9b131a8080 fix: always skip initial gas estimate for Money Account transactions (#33577)
cf1156b16e fix: Polish predict toast for new animation (#32945)
11b4152275 fix: Update DS legacy toast with iOS animation and UI polish (#32933)
a0b1a5199a feat: wire watchlist search functionality (#33530)
10c8db85fe refactor(perps): migrate market details Stats to MMDS KeyValueColumn (#33550)
2b410f8ee2 refactor(perps): migrate Cancel All Orders sheet to MMDS (#33358)
e01ff7de6c feat: add branded share token info sheet on token details (#33319)
d696ba1a1e chore: AB test Buy action (QuickBuy vs Swaps) on Top Traders token screen + feed cp-8.4.0 (#33508)
bca9a43889 fix: invalid JSON RPC errors and reduce Linea calls on wallet unlock (6 -> 2) (#33514)
c34c72b96f feat: add watchlist full empty view (#33492)
bb65abc092 refactor(onboarding): remove A/B test configurations and related components for onboarding checklist stepper (#33483)
55bcd39e7a test: MMQA - 2022 - [Mobile] Fix anti-patterns in flows/accounts.flow.ts (#33487)
a5ac016f86 feat: add QR sync SRP e2e inject path (#33238)
a12e01c403 fix: Update Base Notification toast with iOS animation and UI polish (#32938)
88142bd335 fix: react compiler issues on ChoosePassword and ManualBackupStep1 (#33481)
57018ba3c9 feat(card): add Immersve KYC webview and funding approval (#33548)
da95959b2e chore(ramp): opt in useNavigation to AppNavigationProp (Phase 4) (#33439)
e04b029f2f fix: wire tempMigrateAssetsInfoMetadataAssets3346 into AssetsController init (#33015)
65ed619300 refactor: Aligned more section across wallet and perps (#33391)
ddd741a666 fix: show token letter fallback in activity details avatar (#33467)
eb82e05240 feat(card): add Immersve funding and spending prerequisites (#33540)
6a24a7d580 fix(activity): stop rescaling human-readable ramp buy/sell amounts (#33537)
ed232b8197 chore: bump axios to ^1.18.0 to resolve moderate security advisories (#33541)
dc7702adde feat(card): add Immersve provider foundation (SIWE) (#33515)
864a026bcc chore: patch @metamask/assets-controller for suggested occurrence floors (#33411)
a6f4d69366 fix: remove whole redux state pass through for bridge selectors (#33529)
b0c757a90f fix(ramps): restore RAMPS_TRANSACTION_CONFIRMED for UB2 flows (TRAM-3738) (#33012)
0e85a6d473 chore(component-library): remove unused ListItemMultiSelectWithMenuButton temp component (#33506)
6353d274a8 chore: remove unused HeaderStandardAnimated from components-temp (#33502)
d2a18a46e0 fix: cp-8.4.0 prevent FullWindowOverlay from hiding iOS accessibility tree for Toaster (#33454)
1364bea143 feat: price alert percentage feature (#33339)
e9da46e649 refactor: Migrate transactions/withdraw/deposit progress bar to MMDS and move them above Perps title (#33361)
ce57501c7c fix: android foreground notifications (#33468)
7881e981d0 fix(money): reduce per-keystroke overhead in deposit amount screen (MUSD-1180) (#33465)
5a2edb3188 fix: update push notification content (#33103)
2f63a49452 chore: QuickBuy update direction property as trade_type (#33486)
119acda1c8 fix(money): remove "Steps" heading for single-step mUSD transfers (MUSD-1160) (#33195)
c4085d8dee chore: improve performance of the network selector (#33500)
a0732d2904 fix(money): reduce Add/Transfer bottom sheet open latency (MUSD-1161) (#33210)
2389459356 perf(predict): replace per-card 1s connection-status polling with shared subscription (#33259)
ed7f2f638d fix(money): suppress amount-update error toast on dismissed confirmation (MUSD-1188) (#33491)
bc734cd89a test: remove card detox test (#33484)
cabbe0cd5c feat: add watchlist fullscreen view (#33287)
fed77e9b6a test: MMQA-1996: Migrate smoke/notifications Detox tests to Appium (#33409)
c7b3054f7f feat(stellar): add trustline support in transaction history (#33479)
f09ae8e87c fix(ramps): dynamic per-provider BottomSheet background for checkout WebView (TMCU-1087) (#33429)
99dadfe1c1 chore: migrate Jest preset to @react-native/jest-preset (#33201)
9bc1b132cf chore: replace removed ContextContainer::Shared alias in JNI registry (#33214)
937890b6d4 chore: bump react-native-get-random-values to 2.0.0 (RN 0.85 New Arch) (#33323)
49a35ec205 chore: bump react-native-screens to 4.25.2 (#33121)
23aef41730 chore: bump react-native-svg to 15.15.5 and retarget patch (#33118)
4e58e96efc fix: cp-8.3.0 Fix return undefined token fiat amount instead of locking 1 (#33461)
6df2cbef88 chore(nav): type wallet, asset, and settings shell navigators (Phase 3) (#33306)
d27d2ec148 release: Bump main version to 8.5.0 (#33460)
48fe005243 chore: upgrade MMDS to v54.0.0 (#33455)
8cf01447e6 fix: incorrect non-evm url in useActivityBlockExplorer (#33396)
653aa5fe43 chore(nav): type Money and Ramp nested navigators with NavigatorScreenParams (phase 3) (#33227)
a13e871841 feat: add star icon on trending tokens (#33421)
cccf5bf1d6 chore: remove BUILDS_ENABLED_WITH_GH_ACTIONS_TEMPORARY flag (#32825)
cb3cd9385b chore: Revert "chore: Use expo babel transformer (#33082)" (#33440)
c14a7ba0ee feat(money): add Earn with Money account banner on supported token detail pages (MUSD-1177) cp-8.4.0 (#33412)
ad0f2ea959 feat(home): add homepage 8-button action grid AB test (#33388)
2a7bf19b47 refactor(confirmations): migrate GasFeeTokenModal to MMDS BottomSheet (#33229)
a149195b67 fix: use getPerpsDisplaySymbol on recently viewed rail cp-8.4.0 (#33436)
38781cabd8 refactor(perps): migrate Close All Positions sheet to MMDS (#33365)
9c89318d61 refactor(perps): use MMDS BannerAlert for service interruption banner (#33364)
83b08999eb perf: fix redundant RPC calls on wallet unlock (cache network health metadata + deprecate legacy balance polling) (#33379)
d5d87bf1a9 fix: pure black splash background in dark mode (iOS/Android) (#33360)
ceed3d49f9 refactor(perps): migrate provider selector UI to MMDS (#33363)
f7f64e21f8 ci: request workflows:write for crowdin translation token exchange (#33403)
f736d82ad0 chore(earn): type Earn navigators with feature param lists (Phase 3) (#33291)
ff2a6dfeec fix: raw token amounts shown in asset details activity list (#33211)
4290439de8 perf: unnecessary API calls and NFT performance issues on homepage focus (#33122)
257f20f946 chore: update follow count (#33418)
d4301edd7d fix(activity-redesign): render non-EVM swap/bridge rows with the redesigned row style (#33376)
58ae96f8ff chore: adds label for open feed rows with "Holding" / "Open" (#33404)
7a1497bc80 fix: MUSD deposit from money home page cp-8.3.0 (#33423)
90ce3cffc0 feat: integrate Sentry into QR account sync receive flow (#33316)
59950aa31e chore: emit chain name on follow-trading token events (#33349)
8e5f3a3f81 perf(earn): use memoized selectPendingApprovalIds instead of isEqual … (#33181)
fc817265a2 test: migrate card tests to appium (#33407)
d675c5e831 fix(predict): hide empty related-tag sub-tabs via activeEventsCount cp-8.3.0 (#33399)
92562db632 feat(perps): consume perps controller analytics contract in MetaMask Mobile (#33095)
c904468821 chore: memoize Swaps QuoteRow rendering (#33392)
ce85d95c49 fix(money): skip first-deposit celebration for funded restored accounts (MUSD-903) (#33335)
43eb516ad3 feat(perps): make market detail header identity a tight tap target (#33414)
a9de3d7f27 fix(perps): make market detail price/change row scroll instead of sticky (#33408)
25e0e9b9b3 fix(predict): route Popular Today to Trending cp-8.3.0 (#33373)
19a5383b64 perf(predict): stop REST price polling while live market feed is connected (#33261)
fef858cec8 feat: add support for batch sell on swaps reconciler (#33400)
5a9cc973ca fix: Windows (Git Bash) local development environment compatibility (#33138)
3dccec5762 feat: MUSD-1147 add money account apy to stablecoin earn cta (#33226)
2cb9a53156 fix: Bump react-data-query (#33402)
56721d1849 fix(activity): show one row for gasless sends with token gas fee (#33284)
c261334604 fix(predict): Design QA feedback to the redesigned Predict home and feed cp-8.3.0 (#33382)
24bacc603b perf(login): fix React Compiler blockers in Login screen (#33271)
0230e2cf66 fix(predict): Fix sports card outcome ordering (#33275)
f6dc2d58a6 perf: use createSelector in selectSelectedInternalAccount (#32792)
ff37bcbec7 feat: TDP new theming AB test (#33249)
285cd2e4e3 fix: allow isAuthenticating updates on frozen SecureKeychain (#33406)
db5c0d05d5 fix: guard Nitro Fetch headers check when Headers is unavailable (#33224)
3caf94cb55 fix(e2e): seed SOL into AssetsController for homepage network filter smoke (#33410)
daeee3b39f fix(money): fund Add mUSD via MM Pay fiat deposit instead of standalone Ramps (MUSD-1164) (#33338)
ca991e6a75 ci: run Linux CI on Namespace shadow behind NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH (#33387)
52f3842c68 fix(money): update transaction data when pay token changes on deposit (#33395)
e9c295ede6 chore: support deprecating controller by controller (#33368)
eb29aa1281 fix(predict): remove redundant Live filter chip (#33383)
dd7bf15e81 feat: read stablecoins from stable-tokens LD flag in useTokenFiatRates cp-8.3.0 (#33251)
955fd0a6ff fix: show realized PnL on closed perp feed rows (#33356)
38e16cd043 chore: Use expo babel transformer (#33082)
d7606c0aa3 chore: Upgrade @metamask/delegation-controller from ^2.0.2 to ^3.0.0 (#29834)
e7c210488d chore: open trader position view from feed card tap (#33344)
322dd16d64 chore(send): type Send navigator with feature param list (Phase 3) (#33303)
cef38729cf Revert "feat(perps): enable RoE sign toggle on Auto Close TP/SL (#324… (#33375)
273908b6aa fix(money): show projected 1-year balance in USD (MUSD-1173) cp-8.3.0 (#33333)
5f2cab7c51 chore: migrate to DS slider and use haptics (#33290)
e2b7b1d0e6 chore(bridge): type Bridge navigators with feature param lists (Phase 3) (#33292)
81d497cfe3 chore(card): type Card navigators with feature param lists (Phase 3) (#33283)
c16d9c7580 fix(perps): show long orders in Activity and dedupe perps deposits + clean up (#33235)
5baa9a24cc fix(perps): use live price subscription for header display in trade/close screens (#33099)
8fe6ed511b revert: remove eslint/tsc CI caching (unsafe for cross-file lint rules) (#33370)
96abde95e9 feat: social leaderboard opt out (#32982)
e2db41a167 chore(nav): type Rewards nested navigator with NavigatorScreenParams (#33231)
42e2c2b121 chore(nav): type Predict nested navigators with NavigatorScreenParams (#33219)
8623e6f2a9 fix: ui 'no networks fee' label align center in additional networks (#32898)
35524572cc ci: request workflows:write for release changelog token exchange cp-8.3.0 (#33352)
ed92a6d57d fix(confirmations): use elevated surface on Advanced EIP-1559 modal (#33301)
0017c399e2 test: Wait for top toast before account picker in multi-srp Appium smoke (#33348)
20c7af54f8 refactor: remove unused styles and simplify PhoneCountrySelectorModal… (#33350)
db494587d1 feat(perps): redesign market detail header (TAT-3348) (#33024)
d95691f4c8 fix: MUSD-1175 MetaMask Card "Avail. balance" incorrectly changes based on preferred fiat currency cp-8.3.0 (#33293)
c59a71b642 refactor(engine): wire TransactionController into @metamask/wallet init (#32937)
60905c52f8 chore: update navigation for final step (#33326)
2ef73f3664 fix: cp-8.3.0 convert pay-flow token amounts to USD instead of relabeling (#33321)
dc305bfe56 chore: update trader feed events to match segment-schema (#33320)
234a6829b8 feat: block MetaMask Pay submissions without quotes and handle no-op quotes cp-8.3.0 (#33194)
2df685ca7e feat: migrate mobile-core-ux files from BN.js to native BigInt (#32824)
91b0f055ab test: MMQA-2000: Migrate smoke/ramps Detox tests to Appium (#33334)
ccce7d74d6 fix(predict): Trending too few markets & unstable count cp-8.3.0 (#33336)
d836d925d7 chore: deprecate ActionModal and confirmations BottomModal (#33309)
f40f575903 fix(confirmations): use elevated surface color for TextWithTooltip modal in Pure Black mode (#33300)
94bcd0bab1 fix(confirmations): use elevated surface for edit spending cap modal (#33299)
8a4a01f28c fix(confirmations): use elevated surface color in AdvancedGasPriceModal (#33297)
cdbc2efbb5 fix(confirmations): use elevated surface for AlertModal in Pure Black mode (#33298)
fcab1e8c6b fix(confirmations): use elevated surface color in ConfirmAlertModal for Pure Black (#33296)
fa65c36a22 fix(confirmations): use elevated surface color for value detail modal in Pure Black (#33242)
ea4ea5cc65 fix(confirmations): align Edit network fee sheet with elevated surfaces (#33294)
fb1708de36 fix(confirmations): use elevated surface for CustomNonceModal in Pure Black (#33239)
5d9466a042 fix(money): show USD amounts in Money toasts (MUSD-1174) (#33330)
c3a56fb1fe fix(money): keep Add mUSD tappable and route to Ramps when user has no mUSD (MUSD-1164) (#33250)
a27c73b875 feat(perps): add limit-order support to close position flow cp-8.3.0 (#33197)
9f499fb006 fix(ci): use content-based eslint cache strategy for reliable CI hits (#33327)
887370fcaf fix(predict): use correct payload for dynamic market subscriptions cp-8.3.0 (#33289)
f088cd1d34 chore: relax-price-api-condition-legacy-chart and update to time based index (#33204)
53996cdef5 fix(ci): resilient BrowserStack main reuse + fallback upload (#33277)
da9a364eed chore: New Crowdin Translations by GitHub Action cp-8.3.0 (#33009)
25ef31a7c3 docs: Add deprecation message to BaseNotification (#33123)
def77468b2 feat: show already-synced sheet on duplicate SRP re-sync (#33245)
9bcbf43731 ci: cache eslint and tsc results between ci runs (#33304)
285a54b663 test(perps): remove redundant MMDS BottomSheet mocks (#33288)
d29e494729 fix: oversubscription perps top movers (#33150)
158c8a3361 fix(design-system): remove useElevatedSurface shim from ActionListItem (#33163)
e6d3842193 fix: inject Sentry Debug IDs during Metro bundling (#33220)
f6da752451 chore: bump bridge and bridge status controller for transaction_internal_id in Unified SwapBridge Completed (#33286)
4d571e301b feat: temporary 10-year anniversary app icon cp-8.3.0 (#33280)
c4cb337879 ci: add changelog lint to catch malformed CHANGELOG.md (#33117)
d0795b6291 perf(bridge): migrate token selector to FlashList (#33230)
687f8075cb fix(swaps): backfill sparse post-trade suggestions (#33273)
c4ef40c5da fix(android): share state logs as file attachment instead of path string (#33281)
6411d21cd0 fix: show correct pending status in post strade modal cp-8.3.0 (#33279)
7f340f9e14 fix(money): open all Money account external links in the in-app browser (MUSD-1168) (#33256)
148d14ec5e test: add first integration test - Perps (#29749)
e2928774f2 refactor(perps): migrate Set slippage BottomSheet to MMDS (#33243)
b25f5ac7a2 test: MMQA-2004: Migrate smoke/swap Detox tests to Appium (#33247)
2e564e36ac chore: adds trader feed analytics events (#33252)
0ee3ace5fe fix(perps): horizontally center candle period filter buttons (#33237)
343ba5aaba feat(ramp): Headless Buy all-providers Phase 1 - in-app providers (dev-gated) (#32682)
6e619fd68e fix(activity): stuck confirmation on back after tx + missing lending deposit token icon cp-8.3.0 (#33157)
28a226411b perf(predict): replace RN Image with expo-image across Predict components (#33207)
a23ce45194 feat(money): update Money onboarding Rive animation to v24 (#33260)
d05336bf2e fix(activity): resolve speed-up/cancel dead-end and correct cancelled/failed rows cp-8.3.0 (#33071)
0b264c4c98 fix: include hyperliquid chain in trader feed fetch (#33254)
7317565b53 feat: scam questionnaire on malicious internal send flows (#30717)
65eb9a30e0 fix(money): Activity list amount does not match transaction detail page for mUSD send on Monad (MUSD-1169) (#33258)
d2026ac943 fix(money): correct mUSD casing and list it first on Monad in FAQs (MUSD-1158) (#33190)
a19809e2d4 perf: fix useMemo rest-param dependency in useSDKMethod so stringifiedParams actually memoizes (#32728)
4d61ccc302 feat: add home section watchlist (#33213)
dfef18cd12 test: Add 14 Sell flow CVT tests (#32620)
4fde051106 ci(MMQA-1667): skip native builds when PR only changes E2E/performance tests (#33180)
ac5b30b41b perf(predict): Cache homepage position-row icons with expo-image (#33208)
2684ed12c4 feat: save custom gas settings (#31649)
d5f686adda test: Update Predict E2E to wait for top toast dismiss before back tap (#33244)
cffcbe655e fix(confirmations): use elevated surface for confirmation tooltip modal (#33241)
025842a685 fix(pure-black): align Advanced details Expandable sheet with other elevated sheets (#33152)
2a5ef46f95 fix(confirmations): elevate GasFeeTokenModal surface for pure black claim bonus (#33173)
4a8ff95b4a fix(money): show mUSD withdrawal sends as mUSD instead of mUSD → USDC (MUSD-1159) (#33200)
db43869aa1 fix(money): prevent skeleton jitter and account row flash in card deposit flow (MUSD-1130) (#33039)
ed792c154e fix(snaps): Add missing UI components (#33246)
47b160716d feat(perps): show ticker next to market name in market list rows (#33191)
bb247708df ci(INFRA-3680): rename bot references from mm-token-exchange-service to metamask-ci (#33189)
27e90628f1 refactor: simplify layout nesting for OAuthrehydration, SRP error, and QR scanner (#33179)
fd7785dd44 feat: adds follow trading feed (#33115)
dd2d6f09e0 chore: bump @metamask/tron-wallet-snap to ^1.31.0 cp-8.3.0 (#33225)
2f6b4ea6d8 test(e2e): MMQA-2005 migrate trending smoke tests from Detox to Appium (#32940)
8571c4a5b6 feat: ResetPassword component to improve reauthentication flow and error handling to be react-compiler compatible (#31965)
5c106385ef feat: add new ledger device selection (#30671)
5f89af5ad9 feat(perps): enable RoE sign toggle on Auto Close TP/SL (#32404)
a957368fed fix(ramp): keep amount input visible when opening provider picker (#33132)
11ad8b794f fix(TMCU-1054): remove bg-default from NetworkVerificationInfo root (#33174)
fafc95101b chore: integrate fast-mode stream channel for focus screen views (#32556)
ffd1406246 fix(swaps): clear stale quote before opening batch sell cp-8.3.0 (#33221)
17af786de5 perf(qr): fix React Compiler blockers in QR and network cluster (#32778)
f551ffc05b fix(predict): show retryable error instead of $0 when balance fails to load (#32907)
27cb37022a fix(TMCU-1048): Remove redundant useElevatedSurface from MMDS BottomSheet callsites (#33159)
7719fa3f59 feat: introduce advanced chart analytics (#32365)
9aad058871 feat: recently viewed market list (#32999)
f010f9d598 ci: remove unused error handling during setup (#33218)
ab8d680a5c ci: verbose setup during CI (#33151)
b06f0f6188 fix(pure-black): Network pill and enabled-network list styling (#33143)
2b6e1bddac test: MMQA-1987: Migrate smoke/account-activity Detox tests to Appium (#33196)
64e149d0c0 refactor(market-insights): migrate entry card and disclaimer sheet to use MMDS components (#32861)
088d336c02 chore: update flag default value (#33209)
597b8037cb fix: better check for tron native asset cp-8.3.0 (#33206)
a1e8b199ff refactor(perps): migrate PerpsOrderTypeBottomSheet to MMDS (#33081)
921b70e4d9 feat: implement non prefix ids backwards compatiblity on ramps (#32819)
2eeab87bde fix(settings): translate getAuthLabel authentication labels (#33203)
9400c7f2c3 feat: QrSync syncing metadata (#32502)
f55b27285e feat(social-leaderboard): add TopTraders onboarding flow (#32820)
f388912d0c feat: Bump Snaps packages (#33202)
70977adff1 perf(predict): only fetch market data for the active feed tab (#32935)
801e05c110 feat(transaction-pay-controller): support metamask pay alternate caveats (#32738)
f39f661677 feat: Add minimal analytics for redesigned Predict Home V2 (#32697)
3505b358d7 perf(predict): memoize PredictPositionRow on homepage (#33185)
78a2d326f6 test: MMQA-1995: Migrate smoke/networks Detox tests to Appium (#32804)
c21e66e9cc perf: derive accounts/evmAccounts with useMemo instead of state+effect (#32721)
056a3fdc47 fix(predict): stop reporting transient network errors to Sentry (#33184)
6f0e4fd19b refactor: simplify layout nesting for backup, import, and password screens (#33177)
bb00f4705a feat: prefill token amount to be deposited in MM Pay amount page (#32889)
24080df13e feat: add watchlist star in token details (#32962)
e5e6ae04a7 feat: add more interval support for token details (#33054)
758f4d258e chore: add Quick Buy original_entry_point for trade-screen attribution (#33034)
135e7935de fix: spam warning modal not showing up cp-8.3.0 (#33154)
12f8b0e679 feat: update legend indicator subpane v2 (#33108)
6d8bd7f6f1 refactor(AgenticCliApproval): update approval page path and clean up tests- cp-8.3.0 (#33036)
d8ec071815 fix: import srp password keyboard done (#33171)
458ad3ace4 fix: MUSD-1165 Inconsistency with asset names (#33140)
30a9546f74 feat: MUSD-1140 add sentry tracing for money account balance service network requests (#32995)
1ffca01a97 fix(money): sync activity list row status with transaction toasts (MUSD-1129) (#33125)
c65d38a89a fix(money): pin activity list date headers to design format (MUSD-1125) (#33119)
---

AI Test Plan

Risk Score High Risk Medium Risk Files Changed Teams Signed Off
68/100 10 6 3,023 0/22
Executive Summary

Release Focus: MetaMask Mobile 8.7.0 is a large-scale release delivering a major Perps Pro Mode trading interface, significant Money/Card feature expansions, Bridge/Swaps enhancements, and a sweeping Navbar refactor alongside DeFi positions V2 and Predict feed improvements.

Key Changes:

  • Perps Pro Mode: Entirely new Pro market view with order book panel, position cards, order form with size input, leverage bottom sheet rewrite, limit price bottom sheet rewrite, margin adjustment view rewrite, and mode selection flow — all built on new hooks and utilities
  • Money/Card: New card flip/tilt animations, MoneyAssetOverviewBalanceCta, Immersve legal clickwrap, supported regions hook, onboarding SignUp redesign, MoneyEarnings redesign, and MoneyHomeView/MoneyPotentialEarningsView major refactors
  • Navbar: Massive reduction from ~1400 lines to ~37 lines — nearly all navbar factory functions removed and presumably migrated elsewhere, representing a high-risk regression surface for every screen that used those functions
  • Bridge/Swaps: New PostTradeBottomSheet, RobinhoodSwapsBanner, FlipQuoteButton enhancements, source amount input hook, auto-update dest token hook, and Solana quote mock migration
  • DeFi Positions V2: Entirely new V2 components (DeFiPositionsListV2, DeFiPositionsListItemV2, DeFiProtocolPositionDetailsV2) with new hooks and network filtering utilities

Critical Areas: Navbar refactor — nearly complete rewrite risks breaking navigation headers across all screens, Perps Pro Mode — new order form, order book, position panel, leverage/limit price/margin sheets all introduced simultaneously, Money/Card onboarding and home view — SignUp, Immersve legal clickwrap, MoneyHomeView major refactor, Bridge/Swaps — new post-trade sheet, Robinhood banner, flip quote button, source amount input changes, App.tsx and MainNavigator changes — navigation provider and main navigator both modified, risking deep-link and startup regressions

Overall Risk: HIGH

Recommendation: Conditional go — the Navbar near-complete rewrite and simultaneous Perps Pro Mode introduction represent the highest regression risk. Full regression pass on navigation headers, all major transaction flows (send, swap, bridge), and Perps trading is required before release. Money/Card onboarding and DeFi V2 paths also need dedicated exploratory coverage.

Release Scenarios (16)

High Risk Scenarios (10)

1. Navigation / Navbar

Risk Level: HIGH

Why This Matters: app/components/UI/Navbar/index.js was reduced from ~1400 lines to ~37 lines — virtually all navbar factory functions (getWalletNavbarOptions, getBrowserNavbarOptions, getNetworkNavbarOptions, etc.) were removed. Any screen still importing these functions will crash or render an empty header. The test file was also reduced from 712 to 13 lines, meaning automated coverage was also removed.

Preconditions:

  • Fresh install or existing wallet with at least one account
  • At least one custom network added
  • At least one token and one NFT in wallet

Test Steps:

  1. Launch app and complete unlock — verify the main wallet home screen header renders correctly with account name, network pill, and settings icon
  2. Navigate to Settings via the header — verify the Settings screen header renders with a back button and correct title
  3. Navigate to Settings > Networks — verify the Networks screen header renders with back button and 'Add Network' action button
  4. Navigate to Settings > Contacts > Add Contact — verify the Add Contact screen header renders with back button and save action
  5. Navigate to a token detail screen from the wallet — verify the token detail header renders with back button and token name
  6. Initiate a Send flow — verify the Send screen header renders with back button and correct title
  7. Open the browser and navigate to a dapp — verify the browser header/URL bar renders correctly with back/forward/share controls
  8. Return to wallet home and open account selector — verify the account selector modal header renders correctly

Expected Outcomes:

  • All screen headers render without blank/missing elements on both iOS and Android
  • Back navigation works from every screen that previously used Navbar factory functions
  • Action buttons (save, add, share) in headers are tappable and functional
  • No JavaScript errors or white screens on any navigation transition

2. Perps Pro Mode — Order Form and Order Book

Risk Level: HIGH

Why This Matters: usePerpsProOrderForm.ts (1155 lines), usePerpsProSizeInput.ts (517 lines), and PerpsProOrderBookPanel.tsx (852 lines) are all brand-new files. The size input has complex USD/asset denomination switching with BigNumber precision. The order book integrates with PerpsOrderContext to prefill limit prices. These are entirely untested in production.

Preconditions:

  • User has a funded Perps account with USDC balance
  • User is on a supported network for Perps trading
  • perpsProModeEnabled feature flag is enabled in the test environment

Test Steps:

  1. Navigate to the Perps section and switch to Pro Mode via the mode toggle — verify the Pro market view loads with the order book panel visible on the left and order form on the right
  2. In the order form, tap the Long button — verify the direction control highlights Long and the form updates accordingly
  3. Enter a size in USD denomination in the size input — verify the asset denomination equivalent updates in real time and the slider position reflects the entered amount
  4. Toggle the size denomination to asset units — verify the USD equivalent recalculates correctly using the current market price
  5. Drag the size slider to 50% — verify the USD amount updates to approximately half of max available and haptic feedback fires
  6. Tap an ask price row in the order book — verify the order type switches to Limit and the tapped price prefills in the limit price input
  7. Tap the Confirm/Submit button — verify the order summary sheet appears with correct size, price, fees, and slippage values
  8. Collapse the order book panel using the collapse button — verify the order form expands to full width and the order book is hidden

Expected Outcomes:

  • Size input correctly converts between USD and asset denomination using live price
  • Slider percentage maps correctly to dollar amounts with floor-to-2-decimal behavior
  • Order book price tap correctly sets order type to Limit and prefills price
  • Order summary shows accurate fee and slippage calculations
  • Order book collapse/expand works without layout glitches

3. Perps Pro Mode — Positions Panel and Order Management

Risk Level: HIGH

Why This Matters: PerpsProPositionsPanel.tsx grew from a 27-line scaffold to 493 lines. usePerpsProPositionsPanelActions.tsx is a new 430-line hook wiring close, reverse, TP/SL, margin, cancel, and edit flows. PerpsProOrderCard.tsx and PerpsProPositionCard.tsx are new. The limit price bottom sheet now accepts restingOrderSize/leverage/reduceOnly props for open-order editing — a new code path not previously tested.

Preconditions:

  • User has at least one open Perps position
  • User has at least one open limit order
  • perpsProModeEnabled feature flag is enabled in the test environment

Test Steps:

  1. Navigate to Pro Mode market view — verify the positions panel at the bottom shows the Positions tab with the open position card rendered correctly (symbol, size, PnL, entry price, mark price)
  2. Tap the Orders tab — verify open limit orders are listed with correct price, size, and side
  3. On a position card, tap the Close button — verify the close position flow launches and the position can be closed successfully
  4. On a position card, tap the TP/SL edit button — verify the TP/SL edit sheet opens with current values pre-populated
  5. On a position card, tap the Margin edit button — verify the adjust margin view opens with the correct current margin and max removable amount
  6. On an order card, tap the Cancel button — verify a loading state appears, the order is cancelled, and the card disappears from the list
  7. On an order card, tap the Edit Price button — verify the limit price bottom sheet opens with the current order price pre-populated and incremental margin validation is active
  8. Switch between Positions and Orders tabs multiple times — verify no data loss, no duplicate entries, and correct empty states when applicable

Expected Outcomes:

  • Position cards display accurate PnL with correct color (green/red)
  • Close, TP/SL, and margin edit flows complete without errors
  • Order cancellation removes the order from the list with appropriate feedback
  • Limit price edit with open-order context validates margin correctly
  • Tab switching is smooth with no stale data

4. Perps — Leverage and Margin Adjustment

Risk Level: HIGH

Why This Matters: PerpsLeverageBottomSheet.tsx was rewritten from 601 lines to 383 lines, replacing a custom gesture-based slider with the design-system Slider. PerpsAdjustMarginView.tsx was rewritten replacing PerpsSlider with the design-system Slider and adding new validation logic. PerpsSlider.tsx itself was reduced from 434 to 129 lines, replacing the custom Reanimated gesture implementation with a wrapper around the design-system Slider.

Preconditions:

  • User has a funded Perps account
  • User has at least one open position for margin adjustment testing
  • User is on the Perps market details or Pro market view

Test Steps:

  1. Open the leverage bottom sheet from the order form — verify it renders with the new design-system Slider component (not the old custom gesture-based slider)
  2. Drag the leverage slider from minimum to maximum — verify the leverage value updates in real time and haptic feedback fires at tick marks
  3. Tap a quick-value button (e.g., 5x, 10x) if present — verify the slider jumps to that value and the input reflects it
  4. Confirm the leverage selection — verify the order form updates with the new leverage value
  5. Open the Adjust Margin view for an existing position — verify the slider shows the correct current margin percentage
  6. Drag the margin slider — verify the dollar amount updates using floor-to-2-decimal logic and haptic feedback fires
  7. Enter an amount exceeding the maximum removable margin — verify an error message appears (not while typing, only after input blur)
  8. Tap the Max button — verify the amount sets to the floored maximum and the slider moves to 100%

Expected Outcomes:

  • Leverage slider uses the new design-system Slider with compact variant scaling correctly
  • Margin slider percentage correctly maps to dollar amounts
  • Validation errors appear after blur, not during typing
  • Max button sets correct floored value
  • Haptic feedback fires on grip and tick marks

5. Perps — Mode Selection and Navigation

Risk Level: HIGH

Why This Matters: perpsModeSwitch.ts grew from 1 to 228 lines with new dropPerpsHomeFromStackHistory logic. openPerpsModeSelection.ts is a new 65-line utility. perpsModeSelectionStorage.ts is new. PerpsModeSelectionView.tsx is a new 186-line screen. The PerpsMarketDetailsView now calls openPerpsModeSelectionIfNeeded before every mode toggle. Navigation stack manipulation is inherently fragile.

Preconditions:

  • User has not previously selected a Perps mode (fresh state)
  • User is authenticated and on the main wallet screen

Test Steps:

  1. Navigate to the Perps section for the first time — verify the mode selection view or bottom sheet appears prompting Lite vs Pro selection
  2. Select Lite mode — verify the standard market details view loads correctly
  3. Navigate back and tap the mode toggle pill in the header — verify the mode selection sheet appears (since perpsProModeEnabled is disabled, verify appropriate behavior)
  4. From the market details view, tap the back button — verify navigation returns to the correct previous screen without the Perps home being duplicated in the stack
  5. Navigate to a market, switch to a different market from the positions panel — verify the market view updates to the new market
  6. Deep link into a specific Perps market — verify the correct market loads and the mode selection state is respected
  7. Kill and relaunch the app — verify the previously selected mode is persisted via perpsModeSelectionStorage
  8. Navigate through multiple Perps screens and use the Android back button — verify no navigation stack corruption

Expected Outcomes:

  • Mode selection persists across app restarts
  • Navigation stack does not accumulate duplicate Perps home entries
  • Market switching from positions panel works correctly
  • Back navigation is consistent on both iOS and Android

6. Bridge / Swaps — Post-Trade Flow and Quote Interaction

Risk Level: HIGH

Why This Matters: PostTradeBottomSheet/index.tsx is a new 60-line component. FlipQuoteButton/index.tsx gained 20 lines of new logic. useAutoUpdateDestToken gained new test coverage indicating behavioral changes. useSourceAmountInput/index.ts is a new 21-line hook. normalizeNumericTextInput.ts is a new 198-line utility used across Bridge and Perps. RobinhoodSwapsBanner.tsx is a new 156-line component.

Preconditions:

  • User has ETH or ERC-20 tokens on at least one supported network
  • User has sufficient balance to initiate a bridge or swap
  • App is connected to mainnet or a supported L2

Test Steps:

  1. Navigate to the Bridge/Swap screen — verify the source token selector loads and displays the user's token balances
  2. Select a source token and enter an amount — verify the quote loads and the destination token auto-updates via useAutoUpdateDestToken
  3. Tap the Flip button to swap source and destination tokens — verify the tokens swap correctly and a new quote is fetched
  4. Confirm the transaction — verify the PostTradeBottomSheet appears after submission with correct transaction details
  5. Dismiss the PostTradeBottomSheet and verify the user is returned to the correct screen
  6. Initiate a swap where the Robinhood banner condition is met (if applicable) — verify the RobinhoodSwapsBanner renders without crashing
  7. Test the source amount input with edge cases: enter '0', enter a decimal like '.5', enter an amount exceeding balance — verify each is handled correctly by normalizeNumericTextInput
  8. Check the slippage modal — verify the DefaultSlippageModal renders and allows slippage adjustment

Expected Outcomes:

  • PostTradeBottomSheet appears after successful swap/bridge submission
  • Flip button correctly swaps tokens and triggers new quote
  • Source amount input handles edge cases without crashes
  • Auto-update dest token works when source token changes
  • Slippage modal saves and applies the selected value

7. App Startup and Deep Link Handling

Risk Level: HIGH

Why This Matters: App.tsx gained 88 lines and MainNavigator.js changed significantly (15 additions, 17 deletions). NavigationProvider.tsx was modified. These are the core navigation bootstrap files — any regression here affects every user on every flow. CliLoginPushNudgeListener.tsx was also modified with new logic.

Preconditions:

  • App installed fresh and existing wallet scenarios
  • Push notifications enabled
  • At least one deep link URL available for testing (e.g., metamask://)

Test Steps:

  1. Cold launch the app with an existing wallet — verify the unlock screen appears and biometric/password unlock works correctly
  2. After unlock, verify the main navigator renders the correct initial screen (wallet home)
  3. Tap a MetaMask deep link from an external app — verify the DeepLinkModal handles it correctly and navigates to the right screen
  4. Receive a push notification while the app is in the background — verify tapping it opens the correct screen
  5. Test the CLI login push nudge by simulating a CLI login event — verify the CliLoginPushNudgeListener fires and the nudge UI appears
  6. Navigate to the browser and open a dapp — verify the NavigationProvider correctly tracks the current route
  7. Switch between tabs (Wallet, Browser, Activity) multiple times — verify no navigation state corruption
  8. Force-close and reopen the app — verify state is correctly restored and no crash occurs on startup

Expected Outcomes:

  • App launches without crash on both iOS and Android
  • Deep links route to correct screens
  • Push notification taps navigate correctly
  • Tab navigation is stable across multiple switches
  • NavigationProvider correctly provides navigation context to all consumers

8. Money / Card — Home View and Onboarding

Risk Level: HIGH

Why This Matters: MoneyHomeView.tsx had 92 additions and 70 deletions. SignUp.tsx had 176 additions and 25 deletions. ImmersveLegalClickwrap.tsx is entirely new (118 lines). MoneyEarnings.tsx had 127 additions and 31 deletions. MoneyMetaMaskCard.tsx had 71 additions and 120 deletions — a net reduction suggesting significant restructuring. These are all user-facing financial screens.

Preconditions:

  • User has a MetaMask Money account or is in the onboarding flow
  • earnMoneyHubEnabled feature flag is enabled in the test environment
  • User is in a supported region for Immersve card

Test Steps:

  1. Navigate to the Money home screen — verify MoneyHomeView renders with the correct balance, earnings section, and MetaMask card component
  2. Verify the MoneyMetaMaskCard renders in the correct mode (no card, provisioned, active) based on account state
  3. Tap 'Get Card' or equivalent CTA — verify the Immersve onboarding flow launches
  4. In the SignUp screen, fill in required fields — verify the new SignUp.tsx (176 lines added) renders all fields and validates input correctly
  5. Proceed to the ImmersveLegalClickwrap screen — verify legal documents load and the accept/decline flow works
  6. Check the MoneyEarnings component — verify it renders earnings data correctly with the new layout (127 lines added to MoneyEarnings.tsx)
  7. Tap the MoneyEarnCryptoInfoSheet trigger — verify the info sheet opens with the new content (44 lines added)
  8. Navigate to MoneyPotentialEarningsView — verify the redesigned view (99 lines added) renders without errors

Expected Outcomes:

  • MoneyHomeView renders all sections without blank areas
  • Immersve onboarding SignUp form validates and submits correctly
  • ImmersveLegalClickwrap displays documents and records acceptance
  • MoneyEarnings displays correct earnings data with new layout
  • MoneyPotentialEarningsView renders correctly

9. DeFi Positions V2

Risk Level: HIGH

Why This Matters: DeFiPositionsListV2.tsx (211 lines), DeFiPositionsListItemV2.tsx (155 lines), DeFiProtocolPositionDetailsV2.tsx (111 lines), DeFiProtocolPositionGroupsV2.tsx (68 lines), useDeFiPositionsV2.ts (193 lines), and filter-defi-positions-by-enabled-networks.ts (31 lines) are all brand new. The existing V1 components were also modified. This is a parallel implementation with risk of data mapping errors.

Preconditions:

  • User has DeFi positions on at least one supported network (e.g., Aave, Uniswap)
  • User has multiple networks enabled
  • DeFi positions feature is enabled

Test Steps:

  1. Navigate to the DeFi Positions section — verify the list renders using the V2 components (DeFiPositionsListV2) if the V2 flag is active, or V1 otherwise
  2. Verify each position item (DeFiPositionsListItemV2) displays protocol name, position value, and token breakdown correctly
  3. Tap a position to open DeFiProtocolPositionDetailsV2 — verify the detail view shows all position groups and token amounts
  4. Verify DeFiProtocolPositionGroupsV2 renders token groups with correct icons and values
  5. Disable one of the networks that has DeFi positions — verify filter-defi-positions-by-enabled-networks correctly excludes those positions
  6. Re-enable the network — verify positions reappear
  7. Check the existing V1 DeFiPositionsList — verify it still renders correctly and the new 'Show All' or similar CTA added (19 lines added to DeFiPositionsList.tsx) works
  8. Verify DeFiProtocolPositionGroupTokens renders correctly with the updated styles (10 lines added to styles)

Expected Outcomes:

  • V2 DeFi position components render without errors
  • Network filtering correctly shows/hides positions based on enabled networks
  • Position details show accurate token amounts and values
  • V1 components still function correctly alongside V2
  • No duplicate positions or missing data

10. Card — Immersve Provisioning and Funding

Risk Level: HIGH

Why This Matters: useImmersveCardProvisioning.ts had 50 additions and 20 deletions. useImmersveSupportedRegions.ts is new (82 lines). CardHomeFooter.tsx is new (88 lines). CardAlertSection.tsx had 62 additions and 33 deletions. useMoneyAccountCardLinkage.tsx had 34 additions and 25 deletions. onChainAllowance.ts is new (43 lines). These are all financial transaction paths.

Preconditions:

  • User has completed KYC and is eligible for the MetaMask card
  • User has USDC balance on a supported network
  • immersveOnboardingEnabled is enabled in the test environment

Test Steps:

  1. Navigate to the Card home screen — verify CardHome renders with the correct provisioning state
  2. Initiate card provisioning via useImmersveCardProvisioning — verify the provisioning flow handles the new 50-line additions correctly
  3. Navigate to the AddFundsBottomSheet — verify it renders and the funding flow initiates correctly
  4. Test useImmersveSupportedRegions — verify the hook correctly identifies supported/unsupported regions and blocks or allows onboarding accordingly
  5. Test the CardAlertSection — verify alerts render correctly with the new 62-line additions
  6. Test CardHomeFooter — verify the new 88-line footer component renders with correct CTAs
  7. Verify useMoneyAccountCardLinkage correctly links/unlinks the money account to the card (34 additions, 25 deletions)
  8. Test the onChainAllowance utility — verify allowance checks work correctly for the funding flow

Expected Outcomes:

  • Card provisioning flow completes without errors
  • Region blocking works correctly for unsupported regions
  • Card alerts display relevant information
  • Card footer CTAs are functional
  • Money account card linkage works bidirectionally

Medium Risk Scenarios (6)

1. Predict — Feed and Market List

Risk Level: MEDIUM

Why This Matters: usePredictFeedMarketList.ts is a new 376-line hook replacing or supplementing previous feed logic. feedConfig.ts had major changes (236 additions). PredictFeedBanner.tsx is new (72 lines). Multiple World Cup components were deleted, indicating a feed restructuring. The outcomeGrouping.ts had 128 additions and 17 deletions affecting how market outcomes are displayed.

Preconditions:

  • User has access to the Predict feature
  • predictSportsFeed feature flag is enabled in the test environment
  • Network connectivity is available

Test Steps:

  1. Navigate to the Predict section — verify the feed loads using the new usePredictFeedMarketList hook (376 lines)
  2. Verify the feed config (feedConfig.ts had 236 additions, 45 deletions) correctly structures the market list
  3. Scroll through the market list — verify markets load correctly and pagination works
  4. Tap a market card — verify navigation to the market detail screen works
  5. Verify PredictActionButtons renders correctly with the new 39-line additions
  6. Check the PredictFeedBanner component (new, 72 lines) — verify it renders when the predictFeedBanner flag is enabled
  7. Verify PredictMarketSportCard renders correctly with the updated logic
  8. Test the cash-out flow via usePredictCashOut — verify the 11-line additions handle the flow correctly

Expected Outcomes:

  • Predict feed loads and displays markets correctly
  • Market list pagination works without duplicates
  • Market detail navigation works
  • PredictActionButtons renders correct actions based on market state
  • Cash-out flow initiates correctly

2. Toast Notifications

Risk Level: MEDIUM

Why This Matters: Toast.tsx had 201 additions and 34 deletions — a major rewrite of the core toast component. BaseNotification/index.tsx had 223 additions and 63 deletions. Toast.constants.ts added 22 new constants. usePerpsToasts.tsx and usePredictToastRegistrations.tsx are new hooks. Toast regressions affect user feedback across all major flows.

Preconditions:

  • User is on any screen that triggers toast notifications
  • At least one transaction or action that produces a toast is available

Test Steps:

  1. Complete a swap transaction — verify the success toast appears with correct content using the new Toast.tsx (201 additions, 34 deletions)
  2. Trigger an error condition (e.g., insufficient gas) — verify the error toast renders with the correct severity styling
  3. Verify the new Toast.constants.ts (22 lines added) constants are correctly applied to toast variants
  4. In Perps, trigger a trade confirmation — verify usePerpsToasts (new, 52 lines) fires the correct toast
  5. In Predict, trigger a position cash-out — verify usePredictToastRegistrations (new, 10 lines) fires the correct toast
  6. Trigger multiple toasts in quick succession — verify they queue or stack correctly without UI overlap
  7. Verify BaseNotification component (223 additions, 63 deletions) renders correctly for all notification types
  8. Test toast dismissal — verify tapping dismiss or waiting for auto-dismiss works correctly

Expected Outcomes:

  • Toasts render with correct content, icons, and colors for each type
  • Multiple toasts do not overlap or cause layout issues
  • Toast auto-dismiss timing is correct
  • Perps and Predict toasts fire at the correct moments in their respective flows

3. Account Management — Multi-SRP

Risk Level: MEDIUM

Why This Matters: AccountCell.tsx had 68 additions and 34 deletions — significant restructuring. multiSrp/index.ts had 40 additions and 26 deletions. onboarding/index.ts had 14 additions. AccountRightButton had 20 additions and 15 deletions. These changes affect core account management which is critical for all wallet operations.

Preconditions:

  • User has a wallet with at least one SRP
  • User is on the account management screen

Test Steps:

  1. Navigate to account management — verify the AccountCell component (68 additions, 34 deletions) renders correctly for all account types
  2. Attempt to add a new account via MultichainAddWalletActions — verify the flow works correctly
  3. Test the multiSrp actions (40 additions, 26 deletions in index.ts) — verify adding a new SRP works end-to-end
  4. Verify the onboarding actions (14 additions, 1 deletion) do not break existing onboarding flows
  5. Switch between accounts — verify the AccountRightButton (20 additions, 15 deletions) renders correctly and account switching works
  6. Verify AddressCopy (7 additions, 4 deletions) correctly copies the address to clipboard
  7. Test account import with a seed phrase — verify the import flow completes successfully
  8. Verify the account list renders correctly with the updated AccountCell component for hardware wallet accounts

Expected Outcomes:

  • AccountCell renders correctly for EOA, hardware wallet, and imported accounts
  • Multi-SRP add flow completes without errors
  • Account switching updates the active account across all screens
  • Address copy works correctly
  • Onboarding flow is not broken by the action changes

4. Onboarding Animation

Risk Level: MEDIUM

Why This Matters: onboarding_flow_v25.riv replaced v24 (binary file change). card_tilt_v1.4.riv replaced v1.3. OnboardingAnimation.tsx had 31 additions and 2 deletions. FoxAnimation.tsx and FoxLoader.tsx both gained new lines. Rive animation file replacements can cause crashes if the new file has incompatible state machine names referenced in code.

Preconditions:

  • Fresh app install or cleared app data
  • Device supports animations

Test Steps:

  1. Launch the app for the first time — verify the OnboardingAnimation renders using the new onboarding_flow_v25.riv file (v24 was replaced)
  2. Verify the animation plays smoothly without freezing or crashing
  3. Check FoxAnimation.tsx (9 lines added) — verify the fox animation renders correctly on the onboarding screens
  4. Check FoxLoader.tsx (8 lines added) — verify the fox loader appears during loading states
  5. Complete the onboarding flow — verify all animation transitions are smooth
  6. Test on a low-end device or simulator — verify animations do not cause performance issues
  7. Test with reduce motion accessibility setting enabled — verify animations are appropriately reduced
  8. Verify the card_tilt_v1.4.riv animation (replacing v1.3) plays correctly in the Money card tilt animation component

Expected Outcomes:

  • Onboarding animation plays correctly with the new v25 Rive file
  • Fox animation and loader render without errors
  • Animations respect reduce motion accessibility settings
  • No performance degradation on mid-range devices
  • Card tilt animation works with the new v1.4 Rive file

5. Network Connection Banner

Risk Level: MEDIUM

Why This Matters: NetworkConnectionBanner.tsx had 14 additions and 3 deletions, and a new index.ts export was added. This component is shown to all users when offline and any regression here affects the entire user base's offline experience.

Preconditions:

  • Device with ability to toggle network connectivity
  • App is running with an active wallet

Test Steps:

  1. Disable network connectivity — verify the NetworkConnectionBanner appears with the correct message
  2. Re-enable connectivity — verify the banner dismisses correctly
  3. Verify the new index.ts export (1 line added) does not break existing imports
  4. Test the banner on the wallet home screen — verify it renders above the content without obscuring critical UI
  5. Test the banner during an active transaction — verify it appears and the transaction handles the offline state gracefully
  6. Verify the 14 additions and 3 deletions in NetworkConnectionBanner.tsx do not introduce visual regressions
  7. Test on both iOS and Android — verify the banner layout is correct on both platforms
  8. Simulate intermittent connectivity — verify the banner appears and disappears correctly without flickering

Expected Outcomes:

  • Banner appears promptly when connectivity is lost
  • Banner dismisses when connectivity is restored
  • Banner does not obscure critical UI elements
  • No flickering with intermittent connectivity
  • Consistent behavior on iOS and Android

6. Android App Icon

Risk Level: MEDIUM

Why This Matters: All Android icon files (ic_launcher, ic_launcher_background, ic_launcher_foreground, ic_launcher_round) across all density buckets were changed (binary file changes). NotificationModule.kt had 30 new lines. Icon changes can result in blank icons, distorted icons, or branding inconsistencies that are highly visible to users.

Preconditions:

  • Android device or emulator
  • App installed from the test build

Test Steps:

  1. Install the app on an Android device — verify the app icon displays correctly on the home screen
  2. Verify the icon appears correctly in the app drawer
  3. Check the round icon variant on devices that support it — verify it renders without distortion
  4. Verify the icon at all density buckets (mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi) — verify no pixelation or incorrect scaling
  5. Check the Play Store icon (ic_launcher-playstore.png was changed) — verify it matches the expected branding
  6. Verify the foreground and background layers of the adaptive icon render correctly
  7. Test on Android 8.0+ with adaptive icons — verify the icon clips correctly to the system shape
  8. Verify the notification icon (NotificationModule.kt had 30 additions) renders correctly in the notification shade

Expected Outcomes:

  • App icon displays correctly at all densities
  • Round icon variant renders without distortion
  • Adaptive icon layers composite correctly
  • Play Store icon matches expected branding
  • Notification icon renders correctly

Teams Sign-off Status (0/22)

Awaiting sign-off (22): Accounts, Assets, BE Trade, Card, Confirmations, Core Platform, Design System, Earn, Engagement, MetaMask Delivery, Mobile Platform, Mobile UX, Money Movement, Networks, Onboarding, Perps, Predict, Product Safety, Social & AI, Swaps and Bridge, Transactions, Wallet Integrations

Excluded Features - Feature Flags Disabled (99)

The following features are disabled via feature flags and should NOT be tested:

  • ASSETS3831TestFeatureFlagPermissions
  • addDeviceSyncEnabled
  • agentic_cli_notifications_enabled
  • aiSocialAusCacheRefreshEnabled
  • aiSocialLeaderboardOnboardingEnabled
  • aiSocialLeaderboardOptFlowEnabled
  • assetsGlobalWatchlistV1
  • assetsMemeCoinView
  • bitcoinTestnetsEnabled
  • brazeBannerHome
  • brazeBannerHomeMinVersion
  • brazeSegmentForwarding
  • cardIntercomSupport
  • cardTransactionHistory
  • configRegistryApiEnabled
  • confirmations_pay_hardware
  • coreMCU589AbtestHubPageDiscoveryTabs
  • coreMCU747AbtestPredictPositionsEmptyState
  • crossmintApplePayCheckout
  • earnFeatureFlagTemplate
  • earnMoneyAssetOverviewBalanceCtaEnabled
  • earnMoneyAssetOverviewFooterCtaEnabled
  • earnMoneyCardFlipAnimationEnabled
  • earnMoneyCardTiltAnimationEnabled
  • earnMoneyEarningSectionEnabled
  • earnMoneyHubEnabled
  • earnMoneyParallaxAnimationEnabled
  • earnMusdConversionAssetOverviewCtaEnabled
  • earnMusdConversionFlowEnabled
  • earnMusdConversionRewardsUiEnabled
  • earnMusdConversionTokenListItemCtaEnabled
  • earnMusdCtaEnabled
  • earnPooledStakingServiceInterruptionBannerEnabled
  • earnStablecoinLendingServiceInterruptionBannerEnabled
  • earnMoneyBalanceAnimationEnabled
  • forceRampsStagingEnvironment
  • fullPageAccountList
  • googleLoginIosUnsupportedBlockingEnabled
  • hapticsKillSwitch
  • homeTMCU1209AbtestHomepageBalanceBreakdown
  • homeTMCU470AbtestTrendingSections
  • homeTMCU725AbtestHomepagePerpsPillsEmptyState
  • homeTMCU828AbtestOnboardingChecklistStepper
  • homeTMCU926AbtestDiscoveryPills
  • immersveOnboardingEnabled
  • ledgerDmk
  • legacyIosGoogleConfigEnabled
  • metalCardCheckoutEnabled
  • moneyActivityMockDataEnabled
  • moneyEnableCardActivityEnrichment
  • moneyHomeScreenEnabled
  • moneyShowMoneyAccountAddress
  • pepsSamplePhasedRolloutFlag
  • perpsAdvancedChartEnabled
  • perpsDefaultPayTokenWhenNoBalanceEnabled
  • perpsMyxProviderEnabled
  • perpsPerpGtmOnboardingModalEnabled
  • perpsPerpTradingServiceInterruptionBannerEnabled
  • perpsRecentlyAddedEnabled
  • perpsRecentlyViewedEnabled
  • perpsSlippageConfig
  • perpsCompetitionBannerEnabled
  • perpsMarketAboutEnabled
  • perpsProModeEnabled
  • platformNewLinkHandlerSystem
  • platformTestStructure
  • predictClobV2UseLegacyClobHost
  • predictFeedBanner
  • predictFeedCarousel
  • predictGtmOnboardingModalEnabled
  • predictHomeRedesign
  • predictHotTab
  • predictSportsFeed
  • predictTabFeaturedCarousel
  • predictWimbledon
  • predictWorldCup
  • predictHomepageDiscoveryNbaChampionEnabled
  • rampsServiceDisruptionModal
  • rampsTransakWidgetUrlProxy
  • rewardsAnnouncementModalEnabled
  • rewardsBitcoinEnabled
  • rewardsDropsEnabled
  • rewardsEnableMusdDeposit
  • rewardsEnableMusdHolding
  • rewardsFirstPredictOnUsEnabled
  • rewardsMissingEnrolledAccounts
  • rewardsReferralCodeEnabled
  • rewardsReferralEnabled
  • rewardsTronEnabled
  • socialAiAssetDetailsQuickBuy
  • socialAiTSA495AbtestCardRotationInterval
  • solanaOnboardingModal
  • solanaTestnetsEnabled
  • stellarAccounts
  • tempoConfig
  • tokenDetailsV2ButtonLayout
  • tokenDiscoveryBrowserEnabled
  • tronStaking
  • walletHomeOnboardingSteps

Generated by AI Test Plan Analyzer (claude-sonnet-4-6) at 2026-08-08T00:48:23.512Z

AI generated test plan (JSON): Available as artifact test-plan-8.7.0 in the build workflow

runway-github Bot and others added 2 commits August 9, 2026 06:59
…lur with trailing decimal (#34482)

- fix(perps): commit cleaned USD amount on blur with trailing decimal
cp-8.7.0 (#34421)

<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.

In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
                      comment but do not block the PR.

Sections without a directive are checked for structural presence only.
-->

## **Description**

<!-- mms-check: type=text required=true -->

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

- Fix Pro order form USD size blur so `orderForm.amount` is updated when
a trailing decimal is removed (e.g. `"12."` → `"12"`).
- Align `commitUsdAmount` with limit-price blur by comparing canonical
strings instead of numeric equality.
- Strengthen unit tests to cover the real onChange → parent echo → blur
flow.

## Motivation

When a user types a USD size with a trailing decimal separator and blurs
the field, the UI correctly finalizes the draft (e.g. `"12."` displays
as `"12"`), but `commitUsdAmount` could skip updating canonical order
state.

**Why:** `onChange` already commits the intermediate value (`"12."`) to
`orderForm.amount`. On blur, finalization produces `"12"`, but
`BigNumber("12").eq(BigNumber("12."))` is `true`, so `setAmount` was not
called again. The field looked correct while `orderForm.amount` still
contained the trailing separator.

## Solution

- Replace BigNumber-based skip logic in `commitUsdAmount` with string
equality so `"12."` and `"12"` are treated as different canonical
values.
- Preserve existing empty-amount behavior (`""` vs `"0"`) with an
explicit empty check so denomination toggles and zero handling are
unchanged.
- Update the trailing-decimal blur test to rerender with `usdAmount:
"12."` after `onChange`, and add a case asserting blur does not
re-commit when the amount is already finalized.

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

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

<!-- mms-check: type=issue-link required=true -->

Fixes: https://consensyssoftware.atlassian.net/browse/TAT-3688

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

```gherkin
Feature: Pro order form USD size blur finalization

  Scenario: user blurs a USD size input with a trailing decimal separator
    Given the user is on the Perps Pro order form
    And the USD size field is focused
    And the canonical order size is not already "12."

    When the user types "12." into the USD size field
    And the user blurs the USD size field

    Then the USD size field displays "12"
    And the canonical order size is "12"
    And the canonical order size does not contain a trailing decimal separator
```

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

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

### **Before**

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

### **After**

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

N/A - no visible UI change. The field displayed the finalized value
before and after; the fix aligns canonical orderForm.amount with the
finalized draft.

## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.

Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->

- [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.

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user

SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and

[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance

Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->

- [ ] 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**
> Localized change to Perps Pro size input commit logic with added unit
tests; no auth, security, or broad architectural impact.
> 
> **Overview**
> Fixes a mismatch where the Pro order form **USD size field** looked
finalized on blur but **`orderForm.amount`** could still hold a trailing
decimal (e.g. `"12."`).
> 
> **`commitUsdAmount`** no longer treats `"12."` and `"12"` as the same
via `BigNumber` equality. It compares **canonical strings** first, with
**`isEmptyUsdAmount`** so `""` vs `"0"` behavior stays the same for
empty/zero handling.
> 
> Tests now **rerender** with parent-echoed `usdAmount: "12."` before
blur, and add a case that blur does not call **`setAmount`** when the
amount is already `"12"`.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
fcad6d3. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[c36685e](c36685e)

Co-authored-by: Matt D. <85914066+geositta@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

⏭️ Smart E2E selection skipped - PR targets a release or stable branch (release/* or stable)

All E2E tests pre-selected.

View GitHub Actions results

@socket-security

socket-security Bot commented Aug 11, 2026

Copy link
Copy Markdown

Caution

MetaMask internal reviewing guidelines:

  • Do not ignore-all
  • Each alert has instructions on how to review if you don't know what it means. If lost, ask your Security Liaison or the supply-chain group
  • Copy-paste ignore lines for specific packages or a group of one kind with a note on what research you did to deem it safe.
    @SocketSecurity ignore npm/PACKAGE@VERSION
Action Severity Alert  (click "▶" to expand/collapse)
Block Medium
Network access: npm @hono/node-server in module http

Module: http

Location: Package overview

From: ?npm/@metamask/device-mcp@0.3.2npm/@hono/node-server@1.19.14

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@hono/node-server@1.19.14. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @hono/node-server in module http2

Module: http2

Location: Package overview

From: ?npm/@metamask/device-mcp@0.3.2npm/@hono/node-server@1.19.14

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@hono/node-server@1.19.14. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @hono/node-server in module globalThis["fetch"]

Module: globalThis["fetch"]

Location: Package overview

From: ?npm/@metamask/device-mcp@0.3.2npm/@hono/node-server@1.19.14

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@hono/node-server@1.19.14. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @metamask/client-mcp-core in module node:http

Module: node:http

Location: Package overview

From: package.jsonnpm/@metamask/client-mcp-core@0.8.0

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@metamask/client-mcp-core@0.8.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @metamask/client-mcp-core in module globalThis["fetch"]

Module: globalThis["fetch"]

Location: Package overview

From: package.jsonnpm/@metamask/client-mcp-core@0.8.0

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@metamask/client-mcp-core@0.8.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @metamask/client-mcp-core in module node:net

Module: node:net

Location: Package overview

From: package.jsonnpm/@metamask/client-mcp-core@0.8.0

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@metamask/client-mcp-core@0.8.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
System shell access: npm @metamask/client-mcp-core in module node:child_process

Module: node:child_process

Location: Package overview

From: package.jsonnpm/@metamask/client-mcp-core@0.8.0

ℹ Read more on: This package | This alert | What is shell access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should avoid accessing the shell which can reduce portability, and make it easier for malicious shell access to be introduced.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@metamask/client-mcp-core@0.8.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @metamask/device-mcp in module globalThis["fetch"]

Module: globalThis["fetch"]

Location: Package overview

From: package.jsonnpm/@metamask/device-mcp@0.3.2

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@metamask/device-mcp@0.3.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
System shell access: npm @metamask/device-mcp in module node:child_process

Module: node:child_process

Location: Package overview

From: package.jsonnpm/@metamask/device-mcp@0.3.2

ℹ Read more on: This package | This alert | What is shell access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should avoid accessing the shell which can reduce portability, and make it easier for malicious shell access to be introduced.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@metamask/device-mcp@0.3.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @metamask/tooling-insight in module node:dns/promises

Module: node:dns/promises

Location: Package overview

From: package.jsonnpm/@metamask/tooling-insight@1.0.0

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@metamask/tooling-insight@1.0.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @metamask/tooling-insight in module globalThis["fetch"]

Module: globalThis["fetch"]

Location: Package overview

From: package.jsonnpm/@metamask/tooling-insight@1.0.0

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@metamask/tooling-insight@1.0.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
System shell access: npm @metamask/tooling-insight in module node:child_process

Module: node:child_process

Location: Package overview

From: package.jsonnpm/@metamask/tooling-insight@1.0.0

ℹ Read more on: This package | This alert | What is shell access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should avoid accessing the shell which can reduce portability, and make it easier for malicious shell access to be introduced.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@metamask/tooling-insight@1.0.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Potential security risk (AI signal): npm @modelcontextprotocol/sdk is 70.0% likely risky

Notes: No strong evidence of intentional malware/backdoor behavior in this code fragment (no command execution or covert remote exfiltration). However, the module contains multiple high-impact security anti-patterns: (1) it logs a user-submitted API key in plaintext, (2) it interpolates untrusted values (userSession.name and cartId) directly into HTML without escaping (XSS risk), (3) CORS is configured permissively (origin '*', credentials:true), and (4) elicitation completion appears weakly bound to the presenting MCP session/user context in the shown endpoints. Treat this as high security risk if used beyond a tightly controlled demo environment.

Confidence: 0.70

Severity: 0.73

From: ?npm/@metamask/device-mcp@0.3.2npm/@modelcontextprotocol/sdk@1.29.0

ℹ Read more on: This package | This alert | What are AI-detected potential security risks?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system identified potential security problems in this package. It is advised to review the package thoroughly and assess the potential risks before installation. You may also consider reporting the issue to the package maintainer or seeking alternative solutions with a stronger security posture.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@modelcontextprotocol/sdk@1.29.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm express-rate-limit in module node:net

Module: node:net

Location: Package overview

From: ?npm/@metamask/device-mcp@0.3.2npm/express-rate-limit@8.5.2

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/express-rate-limit@8.5.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm hono in module globalThis["fetch"]

Module: globalThis["fetch"]

Location: Package overview

From: ?npm/@metamask/device-mcp@0.3.2npm/hono@4.12.26

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/hono@4.12.26. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm jose in module globalThis["fetch"]

Module: globalThis["fetch"]

Location: Package overview

From: ?npm/@metamask/device-mcp@0.3.2npm/jose@6.2.3

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/jose@6.2.3. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Low
Publisher changed: npm json-schema-typed is now published by remyrylan instead of jrylan

New Author: remyrylan

Previous Author: jrylan

From: ?npm/@metamask/device-mcp@0.3.2npm/json-schema-typed@8.0.2

ℹ Read more on: This package | This alert | What is new author?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Scrutinize new collaborator additions to packages because they now have the ability to publish code into your dependency tree. Packages should avoid frequent or unnecessary additions or changes to publishing rights.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/json-schema-typed@8.0.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Medium
Medium CVE: Hono: memo() retains SSR output across requests, leading to cross-user data disclosure

CVE: GHSA-f23p-vx2j-j53r Hono: memo() retains SSR output across requests, leading to cross-user data disclosure (MODERATE)

Affected versions: >= 3.8.0 < 4.12.34

Patched version: 4.12.34

From: ?npm/@metamask/device-mcp@0.3.2npm/hono@4.12.26

ℹ Read more on: This package | This alert | What is a medium CVE?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Remove or replace dependencies that include known medium severity CVEs. Consumers can use dependency overrides or npm audit fix --force to remove vulnerable dependencies.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/hono@4.12.26. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Medium
Medium CVE: Hono: Algorithmic Complexity DoS in Language Middleware

CVE: GHSA-54fx-42gc-7vw4 Hono: Algorithmic Complexity DoS in Language Middleware (MODERATE)

Affected versions: >= 4.12.0 < 4.12.34

Patched version: 4.12.34

From: ?npm/@metamask/device-mcp@0.3.2npm/hono@4.12.26

ℹ Read more on: This package | This alert | What is a medium CVE?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Remove or replace dependencies that include known medium severity CVEs. Consumers can use dependency overrides or npm audit fix --force to remove vulnerable dependencies.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/hono@4.12.26. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Potential code anomaly (AI signal): npm @metamask/device-mcp is 62.0% likely to have a medium risk anomaly

Notes: No strong evidence of intentional malware is visible in this fragment. The code is consistent with legitimate UI automation/simulator control, but it performs sensitive actions (clipboard read/write, screenshot/recording capture, log retrieval) and heavily uses subprocess execution driven by caller-provided parameters. The main security risk is whether the unseen exec/execStrict helpers safely avoid shell invocation and correctly validate/escape inputs (especially filter/predicate and user-provided text/paths). This should be reviewed as a high-impact tooling dependency rather than assumed malicious.

Confidence: 0.62

Severity: 0.55

From: package.jsonnpm/@metamask/device-mcp@0.3.2

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@metamask/device-mcp@0.3.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Potential code anomaly (AI signal): npm ajv is 70.0% likely to have a medium risk anomaly

Notes: The code implements a standard AJV-like dynamic parser generator for JTD schemas. There are no explicit malware indicators in this fragment. The primary security concern is the dynamic code generation and execution from external schemas, which introduces a medium risk if schemas are untrusted. With trusted schemas and proper schema management, the risk is typically acceptable within this pattern.

Confidence: 0.70

Severity: 0.60

From: ?npm/@metamask/device-mcp@0.3.2npm/ajv@8.20.0

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/ajv@8.20.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Potential code anomaly (AI signal): npm ajv is 68.0% likely to have a medium risk anomaly

Notes: The code implements standard timestamp validation with clear logic for normal and leap years and leap seconds. There is no network, file, or execution of external code within this isolated fragment. The only anomalous aspect is assigning a string to validTimestamp.code, which could enable external tooling to inject behavior in certain environments, but this does not constitute active malicious behavior in this isolated snippet. Overall, low to moderate security risk in typical usage; no malware detected within the shown code.

Confidence: 0.68

Severity: 0.50

From: ?npm/@metamask/device-mcp@0.3.2npm/ajv@8.20.0

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/ajv@8.20.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Potential code anomaly (AI signal): npm ajv is 70.0% likely to have a medium risk anomaly

Notes: This module generates JavaScript code at runtime via standaloneCode(...) and then immediately executes it with require-from-string. Because the generated code can incorporate user-supplied schemas or custom keywords without sanitization or sandboxing, an attacker who controls those inputs could inject arbitrary code and achieve remote code execution in the Node process. Users should audit and lock down the standaloneCode output or replace dynamic evaluation with a safer, static bundling approach.

Confidence: 0.70

Severity: 0.62

From: ?npm/@metamask/device-mcp@0.3.2npm/ajv@8.20.0

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/ajv@8.20.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Low CVE: Hono: Proxy Helper does not remove response headers listed in the Connection header

CVE: GHSA-79qm-7rj5-m7r9 Hono: Proxy Helper does not remove response headers listed in the Connection header (LOW)

Affected versions: >= 4.7.0 < 4.12.34

Patched version: 4.12.34

From: ?npm/@metamask/device-mcp@0.3.2npm/hono@4.12.26

ℹ Read more on: This package | This alert | What is a mild CVE?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Remove or replace dependencies that include known low severity CVEs. Consumers can use dependency overrides or npm audit fix --force to remove vulnerable dependencies.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/hono@4.12.26. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-8.7.0 Issue or pull request that will be included in release 8.7.0 size-XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.