Skip to content

[pull] main from MetaMask:main#826

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

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

Conversation

@pull

@pull pull Bot commented Jun 11, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


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

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

weitingsun and others added 17 commits June 11, 2026 05:39
<!--
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 blocks the PR
check.

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

## **Description**

<!-- mms-check: type=text required=true -->
1. Migrates Ramp Aggregator Build Quote from stack navigation.setOptions
+ getDepositNavbarOptions to in-screen **HeaderStandard**, with
headerShown: false on Build Quote stack screens. Aligns Aggregator
buy/sell (Routes.RAMP.BUY / Routes.RAMP.SELL) with the native-stack
header pattern.

2. Removes dead setOptions navbar code from Quotes and Checkout (they
already use overlay options with headerShown: false and headers inside
BottomSheet). Updates Quotes cancel tests to use the in-sheet close
button.


## **Changelog**

<!-- mms-check: type=changelog required=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 Ramp Aggregator buy and sell amount screen
headers to use the standard in-app header component.

## **Related issues**

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

Fixes: Ramp screens nav header 

## **Manual testing steps**

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

```gherkin
Feature: Ramp Aggregator Build Quote HeaderStandard
 
Background:
    Given unified buy flags are disabled OR I navigate directly to Routes.RAMP.BUY
    And I open the Aggregator buy or sell Build Quote screen
  
Scenario: Buy flow header shows back and settings
    Given I am on the Aggregator buy Build Quote screen
    Then I see the "Amount to buy" title
    And I see a back button
    And I see the settings button
    When I tap the back button
    Then I leave the Build Quote screen
  
Scenario: Sell flow header shows back without settings
    Given I am on the Aggregator sell Build Quote screen
    Then I see the "Amount to sell" title
    And I see a back button
    And I do not see the buy settings button
  
Scenario: showBack false hides back button
    Given Build Quote is opened with showBack false
    Then the back button is not shown
  
Scenario: Quotes close tracks cancel
    Given I proceed from Build Quote to Quotes
    When quotes load and I tap the close button on the recommended quote sheet
    Then cancel analytics fire for the Quotes screen
  
Scenario: Activity header does not shift on load
    Given I open Activity with the back-button header variant
    Then the header does not jump vertically after render
```

## **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|AFTER|
|---|---|
|<img width="366" height="752" alt="BEFORE"
src="https://github.com/user-attachments/assets/a2081c8e-29a8-48df-8fc2-c48c31fd9778"
/>|<img width="366" height="752" alt="AFTER"
src="https://github.com/user-attachments/assets/4ec25951-5016-4282-96e9-112de6427c9b"
/>|


Android After:
<img width="464" height="892" alt="Android"
src="https://github.com/user-attachments/assets/13422816-5a7c-4b8e-bf82-39926d94c876"
/>


Android Build:
https://github.com/MetaMask/metamask-mobile/actions/runs/27314970757

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

- [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/navigation header refactor in Ramp flows with test updates; no
auth, payments, or data-layer changes beyond existing cancel/back
behavior.
> 
> **Overview**
> Moves Ramp Aggregator **Build Quote** off the native stack header
(`navigation.setOptions` + `getDepositNavbarOptions`) to an in-screen
**`HeaderStandard`**, with **`headerShown: false`** on the Build Quote
stack routes so buy/sell amount screens match the standard in-app header
pattern.
> 
> **Build Quote** now renders title, optional back (default on unless
`showBack: false`), and buy-only settings in the header; back runs
existing cancel analytics then **`navigation.pop()`**. **Quotes** and
**Checkout** drop unused deposit navbar `setOptions` code (those flows
already use overlay headers / bottom-sheet `HeaderStandard`). **Quotes**
tests target the sheet **close** button (`quotes-close-button`) for
cancel analytics instead of the old deposit back navbar control.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
4ab4ffb. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…dict pages (#31529)

<!--
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 blocks the PR
check.

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

## **Description**

Change "Money balance" label to "Money account" on perps / predict
pages.

## **Changelog**

<!-- mms-check: type=changelog required=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/CONF-1528

## **Manual testing steps**
NA

## **Screenshots/Recordings**
NA

## **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**
> Copy and i18n key rename only; no payment or transaction logic
changes.
> 
> **Overview**
> Renames the pay-with **Money** option from **"Money balance"** to
**"Money account"** for confirmation flows (including perps/predict
money-account payment).
> 
> The English string key `confirm.pay_with_bottom_sheet.money_balance`
is replaced with `money_account` in `en.json`, and UI/hooks
(`pay-with-row`, `usePayWithMoneyAccountSection`) plus related tests now
use the new copy.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
1bcd3a5. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
… legacy headless param cleanup (#31480)

## **Description**

Two fixes for the MM Pay / headless fiat deposit flow:

1. **`fiat-order-summary-line`**: Tapping the order-details button on a
fiat deposit in the activity view did nothing, because
`RampsOrderDetails` is registered inside the `TransactionsHome`
(`TransactionsView`) navigator while the summary line renders in the
MoneyModalStack transparent-modal context. The navigate call now uses
the nested-navigator format (`navigate(TRANSACTIONS_VIEW, { screen:
RAMPS_ORDER_DETAILS, ... })`) so the screen is actually reachable.
2. **`BuildQuote`**: Removes the legacy Phase-3 `headlessSessionId`
param and its `failSession` bridging. The headless flow now navigates
straight to `Routes.RAMP.HEADLESS_HOST`, which owns session error
bridging (`nativeFlowError` → `failSession`), so no caller passes this
param to BuildQuote anymore — dead code from the pre-HeadlessHost
architecture.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:
[TRAM-3636](https://consensyssoftware.atlassian.net/browse/TRAM-3636)

## **Manual testing steps**

```gherkin
Feature: Fiat deposit order details from activity

  Scenario: user opens fiat order details from the activity view
    Given the user has completed a fiat deposit via MM Pay

    When user taps the order details button on the deposit row in the activity view
    Then the RampsOrderDetails screen opens with the order's provider and fee details

Feature: BuildQuote regression check (dead-code removal)

  Scenario: user buys via the standard (non-headless) flow
    Given the user opens the Buy flow and lands on BuildQuote

    When user selects an amount and continues with a quote
    Then the flow proceeds normally and provider errors surface on BuildQuote as before
```

## **Screenshots/Recordings**

### **Before**

N/A — order details button did not navigate; BuildQuote change is
dead-code removal with no UI impact.

### **After**



https://github.com/user-attachments/assets/6ad09f97-52fd-4fa3-9541-eb3ef78e2b02



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

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


[TRAM-3636]:
https://consensyssoftware.atlassian.net/browse/TRAM-3636?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Navigation fix is scoped to the fiat activity summary line; BuildQuote
removal is dead code with tests updated and no change to active headless
paths (Checkout/HeadlessHost).
> 
> **Overview**
> Fixes **fiat order details** from activity: the summary line lives
under **MoneyModalStack**, so direct navigation to `RAMPS_ORDER_DETAILS`
never worked. Pressing the button now uses the **root** navigator
(`getParent()`) and nested routing via `TRANSACTIONS_VIEW` →
`RAMPS_ORDER_DETAILS`, with a test for that path.
> 
> **BuildQuote** drops the unused Phase-3 **`headlessSessionId`** param
and all **`failSession`** handling there (native errors and continue
failures). Headless buy goes through **`HEADLESS_HOST`** instead;
standard buy error behavior on BuildQuote is unchanged.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
4dee4fe. 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 Sonnet 4.6 <noreply@anthropic.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.

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

## **Description**

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

UI audit pass for Rewards campaign leaderboard and post-campaign stats
screens (7.82.0).

**Leaderboard screens**
- Remove the total-participants line above the Predict the Pitch
leaderboard list.
- Show the Ondo leaderboard divider under the user position block only
when that section is visible.
- Default loading skeleton row counts to `maxEntries ?? 20` for Ondo,
Perps, and Predict leaderboards.
- Add vertical padding to the Ondo leaderboard empty error state.
- Show a crown icon on Predict leaderboard rows in the top 20 ranks
(main list and neighbor rows).

**Ended campaign stats**
- Refactor Perps post-campaign stats to delegate to the shared
`CampaignEndedStats` component.
- Use shared `rewards.campaign_ended_stats.*` locale keys (including new
`top_pnl`) and remove per-campaign completed-label strings.
- Use `PERPS_TRADING_MAX_WINNERS` from shared constants.

**Misc**
- Group `CampaignLeaderboardStatsHeader` loading skeletons in a spaced
`Box`.
- Update unit tests to match the refactored components.

## **Changelog**

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

CHANGELOG entry: null

## **Related issues**

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

Refs: UI audit 7.82.0

## **Manual testing steps**

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

```gherkin
Feature: Rewards campaign UI audit

  Scenario: Predict the Pitch leaderboard no longer shows total participants header
    Given an active Predict the Pitch campaign with leaderboard data
    When user opens the campaign leaderboard screen
    Then the total participants count line above the list is not shown
    And the leaderboard entries render normally

  Scenario: Perps ended campaign stats use shared layout
    Given a completed Perps Trading campaign
    When user views the campaign details / ended stats section
    Then total participants, volume, top PnL, and winners use the shared ended-stats layout
    And labels match other campaign types

  Scenario: Predict top-20 rows show crown icon
    Given a Predict the Pitch leaderboard with ranked entries
    When user views the leaderboard
    Then rows in the top 20 ranks display a crown icon (when not in preview mode)

  Scenario: Ondo leaderboard divider only when user position is shown
    Given user is opted in with a visible position on the Ondo leaderboard
    When user opens the Ondo leaderboard screen
    Then a divider appears below the user position block
    When user has no visible position
    Then the divider is not shown
```

## **Screenshots/Recordings**

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

N/A — layout and copy alignment changes; no new user-facing flows.

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

<!--
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]
> **Low Risk**
> Presentation-layer changes and test refactors in Rewards campaign
screens; no auth, payments, or core wallet logic.
> 
> **Overview**
> Rewards campaign leaderboard and post-campaign stats get a **UI
audit** pass: layout polish, shared ended-stats UI, and clearer winner
treatment on leaderboards.
> 
> **Leaderboard screens:** The Predict the Pitch leaderboard no longer
shows a **total participants** line above the list (and related tests
were dropped). On Ondo, the divider under the user position block only
appears when that position section is shown. Loading skeletons for Ondo,
Perps, and Predict leaderboards now default to **`maxEntries ?? 20`**
rows instead of a fixed small count; Ondo’s empty error state gains
vertical padding. Predict leaderboard rows in the top
**`PREDICT_THE_PITCH_CAMPAIGN_MAX_WINNERS` (20)** ranks show a **crown**
when not in preview (main list and neighbor rows).
> 
> **Ended campaign stats:** Perps post-campaign stats are **delegated to
`CampaignEndedStats`** instead of bespoke layout and copy; labels use
shared **`rewards.campaign_ended_stats.*`** keys (including new
**`top_pnl`**), and per-campaign “completed label” strings were removed
from locales. Tests now assert props passed into the generic component.
> 
> **Misc:** `CampaignLeaderboardStatsHeader` loading skeletons are
grouped in a spaced `Box`. `PerpsTradingCampaignEndedStats` uses
**`PERPS_TRADING_MAX_WINNERS`** from shared constants.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
e025483. 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 blocks the PR
check.

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

## **Description**

Remove "Max" deposit option from Money deposit page.

## **Changelog**

<!-- mms-check: type=changelog required=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/CONF-1496

## **Manual testing steps**
NA

## **Screenshots/Recordings**
NA

## **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**
> Small confirmation UI change scoped to Money deposits; no auth,
payment routing, or transaction logic is modified in this diff.
> 
> **Overview**
> Removes the **Max** quick-amount shortcut from the Money account
deposit confirmation flow by no longer passing `hasMax` into
`CustomAmountInfo` from `MoneyAccountDepositInfo`.
> 
> Users on that screen get the default percentage shortcuts (including
**90%** instead of **Max**). The unit test that asserted `hasMax={true}`
is removed to match.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
2304a13. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…-649) (#31486)

## **Description**

Restores the blocking behavior that existed before
[#30541](#30541): **only
the `CHANGELOG entry:` check fails the CI workflow**. All other semantic
checks (description, issue link, manual testing, screenshots, checklist)
become informational warnings shown in the sticky comment without
blocking the PR.

Adds a `blocking=true|false` key to the `mms-check` directive grammar
(default `false`). Today only `type=changelog` is tagged
`blocking=true`, matching pre-#30541 behavior. Draft and
ready-for-review PRs follow identical rules (the `isDraft` preview
behavior introduced by #30541 is removed).

**Behavior matrix after change:**

| Scenario | Exit | `INVALID-PR-TEMPLATE` label | Sticky comment |
|---|---|---|---|
| Non-`main` base | 0 | cleared | cleared |
| All headings present, no failures | 0 | removed | deleted |
| All headings present, warnings only | 0 | removed | Warnings section |
| All headings present, blocking failure | 1 | removed | Blocking +
Warnings sections |
| Section heading missing | 0* | **added** | listed under Warnings |
| Section heading missing + blocking failure | 1 | **added** | Blocking
+ Warnings sections |
| Draft PR | same rules as ready-for-review | | |

\* Unless a blocking semantic failure also exists.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MCWP-649

## **Manual testing steps**

```gherkin
Feature: PR template CI check blocking behavior

  Scenario: missing CHANGELOG entry blocks the workflow
    Given a PR targeting main with no CHANGELOG entry line and no no-changelog label
    When the PR template check runs
    Then CI exits 1
    And the sticky comment shows a "Blocking" section with the changelog reason
    And the INVALID-PR-TEMPLATE label is not added

  Scenario: missing description is a warning only
    Given a PR targeting main with a valid CHANGELOG entry but an empty description
    When the PR template check runs
    Then CI exits 0
    And the sticky comment shows a "Warnings" section with the description reason
    And no INVALID-PR-TEMPLATE label is added

  Scenario: draft PR follows the same rules as ready-for-review
    Given a draft PR targeting main with a valid CHANGELOG entry but an empty description
    When the PR template check runs
    Then CI exits 0
    And the sticky comment shows a "Warnings" section (no special draft treatment)

  Scenario: PR targeting a non-main branch skips all checks
    Given a PR targeting a release branch
    When the PR template check runs
    Then CI exits 0 with no validation performed
```

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

- [x] I've tested on Android
- [x] I've tested with a power user scenario
- [x] 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 merge gating and author-facing CI behavior for all PRs
targeting main; misconfigured `blocking` directives could accidentally
block or fail to block merges.
> 
> **Overview**
> Introduces a **`blocking`** flag on `mms-check` directives (default
**`false`**) so each template section can either fail the workflow or
only show up as a warning. **Changelog** is the only section tagged
**`blocking=true`**, matching behavior before #30541; other semantic
checks (description, issue link, manual testing, screenshots, checklist)
are warnings that still appear in the sticky comment but do not fail CI.
> 
> The PR template check orchestrator **drops draft-only “informational”
mode**—draft and ready-for-review PRs use the same rules.
**`INVALID-PR-TEMPLATE`** is applied only when required **section
headings** are missing; semantic issues no longer add that label. Exit
status is driven by whether any **blocking** failure exists (`setFailed`
/ exit 1 vs `core.warning` / exit 0). Sticky comments are split into
**Blocking** and **Warnings** sections instead of a single
draft-dependent message.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
fa07a08. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

The trade list under a trader position was filtered by the active chart
time period (default: 1M), which hid trades that fell outside the window
eventhough the API returns them all. Positions opened more than a month
ago looked like they had zero trades.

`useTraderPositionData` now returns two derivations of the same trade
array:

- **`allTrades`** — pass-through of `positionParam?.trades`. Fed to
`TraderTradesSection` so the list always shows every trade for the
position.
- **`chartTrades`** — filtered to the active period via
`PERIOD_DURATION_MS`. Fed to `TraderPositionChartSection` so the
buy/sell dot markers on the price chart still match the visible price
window.

`TraderPositionView` wires each derivation to its respective consumer.
No backend changes — `SocialService.fetchPositionById` already returns
all trades. Empty-state copy updated from "No trades for this interval"
to "No trades yet" to match the new "always all" behavior.

> Note: when TSA-146 (AdvancedChart integration) lands, `chartTrades`
will feed> the new `SET_TRADE_MARKERS` bridge message instead of the SVG
markers — the derivation stays, only the transport changes.

## **Changelog**

CHANGELOG entry: Fixed a bug where the trade list on a trader position
only showed trades inside the active chart time period, hiding older
trades that still belonged to the position.

## **Related issues**

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

## **Manual testing steps**

  ```gherkin
  Feature: Trader position view — trade list shows all trades

    Scenario: Trade list is unaffected by chart time period
Given I am viewing a trader position whose trades span more than a month
      And the chart time period is the default (1M)
      When I switch the chart time period to 1H, 1D, 1W, or All
      Then the trade list continues to show every trade for the position
And only the chart buy/sell dot markers narrow to the selected period

    Scenario: Position with no trades
      Given I am viewing a trader position that has no trades
      When the view renders
      Then the trade list shows the "No trades yet" empty state
```

## **Screenshots/Recordings**

### **Before**
<img width="447" height="974" alt="Screenshot 2026-06-10 at 3 43 43 PM" src="https://github.com/user-attachments/assets/040d38bf-0bd9-43cd-8179-861bd174865a" />
<img width="447" height="974" alt="Screenshot 2026-06-10 at 3 43 54 PM" src="https://github.com/user-attachments/assets/617fe248-c9a6-403a-8332-3f25ce3f831b" />


### **After**
<img width="447" height="974" alt="Screenshot 2026-06-10 at 3 41 50 PM" src="https://github.com/user-attachments/assets/7ca81a86-8df8-4161-b40a-c0b42beacca3" />


## **Pre-merge author checklist**

- [x] I've followed MetaMask Contributor Docs and MetaMask Mobile Coding Standards.
- [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 format if applicable
- [x] I've applied the right labels on the PR (see labeling guidelines). 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 to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production performance metrics
  - See trace() for usage and addToken for an example

For performance guidelines and tooling, see the Performance Guide.

## **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 data wiring and copy in Social Leaderboard trader position view; no API or auth changes, with tests updated for the new behavior.
> 
> **Overview**
> Fixes trader positions where the **trade list** only showed trades inside the active chart window (e.g. default **1M**), so older trades looked missing even though the API returns the full set.
> 
> `useTraderPositionData` now exposes **`allTrades`** (full `position.trades`) and **`chartTrades`** (still filtered by `PERIOD_DURATION_MS` for the selected period). **`TraderPositionView`** passes **`allTrades`** to **`TraderTradesSection`** and **`chartTrades`** to **`TraderPositionChartSection`**, so changing **1H / 1D / 1W / 1M / All** only narrows chart buy/sell markers, not the list.
> 
> Empty-state copy changes from **"No trades for this interval"** to **"No trades yet"** in `en.json`, with matching test updates.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit c7aa599. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

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

A recent change added a `blocking: boolean` field to the
`PrTemplateCheckResult` failure variant so `runAllChecks` could signal
whether a check is CI-blocking. However, individual validators (e.g.
`hasNonEmptyDescription`, `hasChangelogEntry`) were still typed as
returning `PrTemplateCheckResult`, which forced them to carry the
`blocking` field — a concern they have no business knowing about.

This broke TypeScript compilation on every unrelated PR whose CI ran
`yarn lint:tsc`, producing:

```
Type '{ ok: false; reason: string; }' is not assignable to type 'PrTemplateCheckResult'.
```

The fix introduces a narrower internal `ValidatorResult` type (without
`blocking`) for the 6 individual validators and the `Validator` function
alias. `runAllChecks` already stamps `blocking` from the plan entry via
`{ ...result, blocking: entry.blocking }`, so `PrTemplateCheckResult`
(with `blocking`) remains the correct output type for that public
function only.

> [!NOTE]
> Why neither yarn lint:tsc nor Jest caught the type error
>
> yarn lint:tsc runs tsc --project tsconfig.json, whose include only
covers app/**/*, tests/**/*, and scripts/**/*. The .github/scripts/
directory is entirely outside that project boundary, so tsc never sees
those files. The commit hook runs the same command, so it has the same
blind spot.
>
>Jest uses Babel (babel-jest) to transpile TypeScript before running
tests. Babel is a transpiler, not a type-checker — it strips all type
annotations and runs the plain JavaScript. A type mismatch like
returning { ok: false, reason: string } where { ok: false, reason:
string, blocking: boolean } is expected is invisible to Babel and
therefore invisible to Jest.
>
>The result: both gates passed, yet the production tsc invoked by the
GitHub Actions CI workflow (which does point at .github/scripts/) caught
the error when another PR ran against main.
>
>Fix applied: introduced a narrower ValidatorResult type for the return
of individual validator functions (without blocking), keeping blocking
only on the PrTemplateCheckResult produced by the orchestrator —
eliminating the mismatch.
>
>Longer-term guard: add a dedicated tsconfig.json inside
.github/scripts/ and a CI step that runs tsc --noEmit against it, so
these scripts are type-checked on every PR.

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

Refs: #31486

## **Manual testing steps**

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

```gherkin
Feature: PR template CI check compilation

  Scenario: TypeScript compilation succeeds
    Given a developer opens a PR
    When the CI job runs yarn lint:tsc
    Then TypeScript compilation completes without errors
    And the PR is not incorrectly blocked by a type mismatch
```

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

<!-- Generated with the help of the pr-description AI skill -->
…perties (#31471)

<!--
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 blocks the PR
check.

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

## **Description**

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

The perps MetaMetrics documentation
(`docs/perps/perps-metametrics-reference.md`) had fallen behind the
codebase. This PR brings it up to date by:

- Adding the undocumented **9th event** `PERPS_ACCOUNT_SETUP` (`'Perp
Account Setup'`) with its full property schema (`status`,
`abstraction_mode`, `previous_abstraction_mode`, `error_message`). This
event is fired from the controller's `HyperLiquidProvider` during
unified account (HIP-3) migration.
- Adding 4 missing `interaction_type` values to `PERPS_UI_INTERACTION`:
`cancel_trade_with_token`, `slippage_config_opened`,
`slippage_config_changed`, `slippage_limit_blocked_order`.
- Adding the missing `cancel_trade_with_token_toast` screen type to
`PERPS_SCREEN_VIEWED`.
- Documenting new properties: `max_slippage_pct`, `max_slippage_source`,
`estimated_slippage_pct`, `section_viewed`, `location`,
`market_insights_displayed`.
- Adding missing source values (`home_section`, `market_insights`,
`cancel_all_orders_button`), action value (`connection_go_back`), and
setting type (`slippage`).
- Annotating `competition_banner_engage`/`competition_banner_close` as
local constants pending upstream addition to `PERPS_EVENT_VALUE`.
- Fixing "Related Files" references to point to the correct
`@metamask/perps-controller` npm package paths instead of non-existent
local controller files.
- Updating event count from 8 to 9 across overview, section heading, and
comparison table.

## **Changelog**

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

CHANGELOG entry: null

## **Related issues**

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

Refs: N/A — documentation-only update to match existing code.

## **Manual testing steps**

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

```gherkin
Feature: Perps MetaMetrics documentation accuracy

  Scenario: Developer reviews perps MetaMetrics reference
    Given the developer opens docs/perps/perps-metametrics-reference.md

    When the developer reads the event reference
    Then 9 consolidated events are documented (including PERPS_ACCOUNT_SETUP)
    And all interaction_type values match PERPS_EVENT_VALUE.INTERACTION_TYPE in @metamask/perps-controller
    And all screen_type values match PERPS_EVENT_VALUE.SCREEN_TYPE in @metamask/perps-controller
    And the Related Files section references the correct npm package paths
```

## **Screenshots/Recordings**

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

N/A — documentation-only change, no UI impact.

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

Gates all VIP rewards surfaces behind the existing app-wide
`vipProgramEnabled` remote feature flag (`selectVipProgramEnabled`,
`app/selectors/featureFlagController/vipProgram`). This is the broader
app flag already consumed by the Perps fee hooks and `useVipTier` — this
PR extends the same gate to the rewards controller and the rewards VIP
UI surfaces.

When the flag is OFF:

- The homepage VIP icon does not render, which implicitly prevents
  navigation into the VIP screens.
- The VIP splash page is unreachable (redirects to the dashboard).
- `RewardsController` VIP methods short-circuit: `getVIPDashboard` and
  `getVipTierForAccount` return `null`, and `getPerpsDiscountForAccount`
  returns `null` (no discount applied).

### Implementation

- Threaded an `isVipDisabled` callback into the `RewardsController`
  constructor, mirroring the existing `isDisabled` rewards-feature gate.
  Added `isVipFeatureEnabled()` which ANDs the rewards gate with the VIP
  gate (VIP is a sub-feature of rewards). Exposed it via the messenger
  (`RewardsController:isVipFeatureEnabled`).
- Wired `selectVipProgramEnabled` into the controller init
  (`rewards-controller/index.ts`) following the exact pattern used for
  `selectBasicFunctionalityEnabled`.
- Gated `RewardsDashboard` VIP icon render and `RewardsVipSplashView`
  reachability with `selectVipProgramEnabled`.

## **Changelog**

CHANGELOG entry: VIP rewards surfaces (home VIP icon, VIP splash page)
and VIP controller endpoints (`getVIPDashboard`, `getVipTierForAccount`,
`getPerpsDiscountForAccount`) are now gated behind the
`vipProgramEnabled` feature flag.

## **Related issues**

Refs: N/A

## **Manual testing steps**

1. With `vipProgramEnabled` OFF: open Rewards home as a VIP-eligible
   subscription — the crown/VIP icon should not appear; deep-linking to
   the VIP splash route should bounce back to the dashboard; perps fee
   estimates should show no VIP discount.
2. With `vipProgramEnabled` ON: VIP icon renders for VIP subscriptions,
   splash is reachable, and the perps VIP discount applies as before.

## **Screenshots/Recordings**

N/A — gating only; no new 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)

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

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes when perps VIP discounts and VIP dashboards apply (fee/pricing
UX) and add a second gate on rewards VIP navigation; behavior is
flag-driven with broad test coverage but touches money-adjacent
controller paths.
> 
> **Overview**
> VIP rewards behavior is now tied to the remote **`vipProgramEnabled`**
flag via **`selectVipProgramEnabled`**, in addition to existing
subscription VIP checks.
> 
> **Rewards UI:** The dashboard VIP icon only shows when both the
program flag and subscription VIP are on. Splash, main VIP, and tiers
views treat **`canViewVip`** as requiring the flag and redirect to the
dashboard when it is off (including deep links).
> 
> **RewardsController:** An **`isVipDisabled`** constructor callback
(wired from **`selectVipProgramEnabled`** at init, like basic
functionality for rewards) drives new **`isVipFeatureEnabled()`**
(rewards enabled AND VIP not disabled). VIP APIs **`getVIPDashboard`**,
**`getVipTierForAccount`**, and **`getPerpsDiscountForAccount`**
short-circuit when VIP is disabled instead of using only
**`isRewardsFeatureEnabled`**.
> 
> Tests were updated across dashboard/VIP views, controller init, and
controller unit tests for flag-off behavior.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
57ac167. 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 Sonnet 4.6 <noreply@anthropic.com>
…a polish (#31474)

## **Description**

Polishes the QuickBuy (Trader Position) flow and adds slider haptics,
addressing the UI nits and haptic-feedback request in
[TSA-589](https://consensyssoftware.atlassian.net/browse/TSA-589).


**What changed and why:**

1. **Trade-mode toggle — lively red/green sliding fill.** The Buy/Sell
toggle's sliding pill now animates its background from vivid green (Buy)
to vivid red (Sell), interpolating the color as it slides so the
transition tracks the thumb. The active label switches to
`PrimaryInverse` for contrast on the saturated fill.
2. **Trade-mode toggle — fixed vertical gap.** The pill previously sat
~1px low (the button's measured `y` double-counted the container border,
which an absolute child's `top` already accounts for), leaving a larger
dark gap at the top than the bottom. The slider now lives in a
borderless/padding-less inner row and fills it with `top: 0` / `bottom:
0`, so the only inset is the uniform outer padding — symmetric top and
bottom.
3. **Trade-mode toggle — sized to match Figma.** Buttons now use
`BodyMd` text, `px-4`, and `rounded-lg` (8px), bringing the container to
the design's 40px height (was ~36px).
4. **Amount slider — grip haptics.** Added `ImpactMoment.SliderGrip` on
pick-up (pan start) and drop (pan end), per the ticket, matching the
Perps implementation and distinct from the existing per-tick
`SliderTick` crossings.
5. **Conversion-rate tag — radius fix.** `rounded-full` → `rounded-md`
(6px) to match the design (no longer a full pill).
6. **Pay-with / Receive selector — removed pill background.** The inline
selector dropped its `bg-muted` rounded-full pill to match the design,
which has no background.

Design reference: [Figma — Swap Next, QuickBuy
sheet](https://www.figma.com/design/GO9uJiYlhdWRuXJe8dzZfR/Swap-Next?node-id=2236-26517).

## **Changelog**

CHANGELOG entry: null

<!-- UI polish + haptics scoped to the in-development QuickBuy flow; not
separately user-facing for release notes. -->

## **Related issues**

Fixes: [TSA-589 — UI nits + Implement haptic feedback on the amount
slider](https://consensyssoftware.atlassian.net/browse/TSA-589)

## **Manual testing steps**

```gherkin
Feature: QuickBuy toggle, slider haptics, and UI polish

  Scenario: Trade-mode toggle shows transitioning red/green fill
    Given the QuickBuy sheet is open in Buy mode
    Then the sliding pill is green behind the "Buy" label
    When the user taps "Sell"
    Then the pill slides across and its background transitions from green to red
    And the dark gap above and below the pill is equal

  Scenario: Amount slider grip haptics
    Given the QuickBuy sheet is open with a sellable balance
    When the user presses and starts dragging the amount slider
    Then the device plays a grip haptic on pick-up
    When the user lifts their finger
    Then the device plays a grip haptic on drop

  Scenario: Conversion-rate tag and pay-with selector styling
    Given the QuickBuy sheet is open
    Then the conversion-rate tag uses a 6px corner radius (not a full pill)
    And the "Pay with" / "Receive" selector has no pill background
```

## **Screenshots/Recordings**

<img width="2705" height="1858" alt="image"
src="https://github.com/user-attachments/assets/f37c682f-f261-40ba-966c-50a9a1b2d1c8"
/>

### **Before**

<!-- Current iOS build: rate tag is a full pill, pay-with selector has a
muted pill background, toggle is smaller with a uniform muted fill, and
the pill sits slightly low. -->

N/A

### **After**

<!-- Matches the Figma design above: vivid green/red transitioning
toggle (taller, symmetric), 6px-radius rate tag, and a borderless
pay-with/receive selector. Screenshots/recording to be attached. -->

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)

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

🤖 Generated with [Claude Code](https://claude.com/claude-code)


[TSA-589]:
https://consensyssoftware.atlassian.net/browse/TSA-589?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Scoped UI and haptic feedback in the in-development QuickBuy flow; no
changes to swap execution, auth, or payment logic.
> 
> **Overview**
> Polishes the **QuickBuy** sheet UI to match Figma and adds
**amount-slider grip haptics** (TSA-589).
> 
> The **Buy/Sell toggle** now uses a sliding pill that interpolates
**green → red** as it moves to Sell, with **PrimaryInverse** labels on
the active side. Layout is fixed by moving the pill into a borderless
inner row (`top`/`bottom` fill) so vertical gaps are symmetric; buttons
are taller (`BodyMd`, `px-4`, `rounded-lg`). Animation runs with
**`useNativeDriver: false`** so `backgroundColor` can animate.
> 
> **QuickBuyPercentageSlider** fires **`ImpactMoment.SliderGrip`** on
pan start and pan end (separate from existing **SliderTick** at
25/50/75%), with new unit tests.
> 
> Minor styling: **conversion-rate tag** uses **`rounded-md`** instead
of a full pill; **Pay with / Receive** row drops the muted pill
background on the token selector.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
d9a2a3d. 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 4.8 (1M context) <noreply@anthropic.com>
…wn (#31544)

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

When the Select Quote bottom sheet displayed 4 or more quotes, the list
overflowed the visible area and overlapped the device's rounded corners
and home indicator with no way to scroll to the last quote. This fix
wraps the quote list in a `ScrollView` (from
`react-native-gesture-handler`) in `QuickBuySelectQuoteScreen`, keeping
the header sticky above the scrollable content so all quotes are fully
accessible regardless of how many are returned.

## **Changelog**

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

CHANGELOG entry: null

## **Related issues**

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

Fixes: #31464

## **Manual testing steps**

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

```gherkin
Feature: Select Quote bottom sheet scrollability

  Scenario: User can scroll when 4 or more quotes are available
    Given the user is on a token detail screen (e.g. SOL) with the Quick Buy sheet open
    And the token has 4 or more bridge/swap quotes available

    When the user taps the rate row to open the Select Quote screen
    Then all quotes are visible and the list is scrollable

    When the user scrolls down
    Then the last quote is fully visible and does not overlap the device corners or home indicator

    When the user taps a quote
    Then the sheet navigates back to the Quote Details screen with the selected quote applied
```

## **Screenshots/Recordings**

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

### **Before**

N/A

### **After**


https://github.com/user-attachments/assets/1b3f0716-c70a-4eca-a194-226a7c161ec6


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

## **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**
> Localized layout change to one Quick Buy screen; no swap, quote
selection, or transaction logic is modified.
> 
> **Overview**
> Fixes overflow on the Quick Buy **Select Quote** bottom sheet when
many bridge quotes are returned by making the quote list scrollable
while keeping `QuickBuySubScreenHeader` fixed above it.
> 
> The info text and `QuoteRow` list are wrapped in a
`react-native-gesture-handler` `ScrollView` with `flex: 1`,
`keyboardShouldPersistTaps="handled"`, and hidden vertical scroll
indicators—matching the scroll pattern used on other Quick Buy
sub-screens.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
55af212. 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 blocks the PR
check.

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

Same-chain Solana swaps could stay stuck in the post-trade bottom sheet
because they do not terminalize through `BridgeStatusController` and
their placeholder `TransactionController` entry never reaches
`confirmed`.

This change keeps the existing bridge/EVM status flow intact, but
detects same-chain Solana swaps from the bridge history quote and
resolves their terminal status from `MultichainTransactionsController`
using the Solana transaction signature. Solana-sourced cross-chain
bridges still wait for bridge status, so a confirmed source transaction
alone does not mark the bridge as successful.

## **Changelog**

<!-- mms-check: type=changelog required=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 a bug that caused same-chain Solana swaps to
remain stuck as in progress after completion.

## **Related issues**

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

Refs: Slack-reported same-chain Solana post-trade status bug

## **Manual testing steps**

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

```gherkin
Feature: Same-chain Solana post-trade status

  Scenario: user completes a same-chain Solana swap
    Given the user submits a same-chain Solana swap
    When the Solana transaction is confirmed on-chain
    Then the post-trade bottom sheet changes from in progress to success

  Scenario: user submits a Solana-sourced cross-chain bridge
    Given the user submits a Solana-sourced cross-chain bridge
    When only the source Solana transaction is confirmed
    Then the post-trade bottom sheet remains in progress until bridge status reaches a terminal state
```

## **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 - logic-only status resolution fix.

### **After**

N/A - logic-only status resolution fix.

## **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 post-trade UX status logic for Solana swaps with new hash
fallbacks; scope is limited to the hook and covered by tests, but wrong
matching could show success/failure incorrectly.
> 
> **Overview**
> Fixes the post-trade bottom sheet staying **in progress** after
same-chain Solana swaps complete.
> 
> **`usePostTradeTxStatus`** still uses EVM `TransactionController` and
bridge history for most flows. For **non-bridge** trades whose
bridge-history quote is **Solana source**, it now looks up the submitted
signature (meta hash, `transactionHash`, or bridge `srcChain.txHash`) in
**`selectMultichainTransactions`** and maps keyring **Confirmed** /
**Failed** to success or failed. **Solana-sourced cross-chain bridges**
(`isBridge: true`) are unchanged and keep waiting on bridge status.
> 
> Tests mock multichain transactions and cover success, failure, empty
meta hash, cross-chain in-progress, and hash fallback paths.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
675e5d2. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…heets (MUSD-944) (#31470)

<!--
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 blocks the PR
check.

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

Aligns the Money Home primary actions and both funds bottom sheets with
the latest design (MUSD-944):

- The Send primary action now uses the `arrow-2-up-right` icon and the
label "Send" (previously `swap-horizontal` / "Transfer"). Add and Card
are unchanged.
- Add funds sheet: the debit card row is relabeled "Debit card or bank"
with a bank icon, the mUSD row reads "Your [balance] mUSD" (balance
stays dynamic via `useMusdBalance`), the external row reads "External
wallet", and the per-row description subtitles are removed per design.
- Send funds sheet: the title is now "Send funds to", the coming-soon
rows are relabeled "External address" and "Bank", and the "Another
account" row uses the `arrow-2-up-right` icon per design.

Internal names (`MoneyTransferSheet`, route constants, testIDs, locale
keys, analytics constants) are deliberately kept to preserve analytics
continuity; only user-facing copy and icons change. Existing MUSD-868
gating logic (hiding/disabling rows based on ramp support and balances)
is preserved. Only `en.json` is touched among locale files; translations
flow through the localization pipeline.

## **Changelog**

<!-- mms-check: type=changelog required=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 the Money Home Send action icon and label, and
refreshed the Add funds and Send funds bottom sheet copy

## **Related issues**

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

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

## **Manual testing steps**

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

```gherkin
Feature: Money Home send action and funds sheets

  Scenario: user views the primary actions
    Given the user is on the Money Home screen

    When user looks at the primary action row
    Then the middle action shows the arrow-2-up-right icon with the label "Send", and Add and Card are unchanged

  Scenario: user opens the Add funds sheet
    Given the user is on the Money Home screen with an mUSD balance

    When user taps the "Add" action
    Then the "Add funds" bottom sheet appears with the rows "Convert crypto", "Debit card or bank", "Your [balance] mUSD" showing the current mUSD balance, and "External wallet" tagged "Coming soon" and non-tappable

  Scenario: user opens the Send funds sheet
    Given the user is on the Money Home screen

    When user taps the "Send" action
    Then the "Send funds to" bottom sheet appears with the rows "Another account", "Perps account", "Predictions account", and "External address" and "Bank" both tagged "Coming soon" and non-tappable
```

## **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/e793fd54-ab86-4776-8f71-86e57bef12e9


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

- [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**
> User-facing strings and icons only; deposit, transfer, and
feature-flag behavior are unchanged.
> 
> **Overview**
> Aligns Money Home **Send** and the Add/Send funds bottom sheets with
updated design copy and icons (MUSD-944).
> 
> The middle primary action now uses **`Arrow2UpRight`** and the label
**Send** (was swap-horizontal / Transfer). **Add funds** drops per-row
subtitles, relabels rows (**Debit card or bank** with a bank icon,
**Your {{amount}} mUSD**, **External wallet**), and keeps the same
deposit/move handlers and ramp gating. **Send funds** uses title **Send
funds to**, shorter destination labels (**External address**, **Bank**),
and the same arrow icon on **Another account**. English strings in
`en.json` and `MoneyAddMoneySheet` tests are updated to match; internal
testIDs and analytics identifiers are unchanged.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
94e790a. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…-913, MUSD-935) (#31266)

## **Description**

Removes the funding bottom sheet from the Money balance card's primary
CTA on the wallet home screen and routes funding directly into the
deposit/Buy flow, and simplifies the CTA so it only ever renders "Earn"
or "Add".

**What changed**
- **MUSD-913** — Tapping the card's Add/Earn CTA no longer opens the
`MoneyAddMoneySheet` bottom sheet. It now routes funding directly via
the shared `routeAddMoney` from the `useMoneyAccountAddRouting` hook —
the **same routing the Money "How it works" Add button uses** — so both
entry points share one decision instead of the card carrying its own
gate. The decision is based on mUSD holdings: when the user holds mUSD
(on any supported chain, or a positive aggregated mUSD fiat balance) it
opens the MM Pay deposit screen with `addMusd` intent and the
highest-balance mUSD token preselected; otherwise it opens the Ramp
**Buy** flow for mUSD.
- **MUSD-935** — Removed the "Get Started" CTA variant entirely. The
card now always renders "Earn" (zero/empty balance) or "Add" (balance >
0), never "Get Started".

**Why**
Reduces friction when funding the Money account from the home screen and
removes an inconsistent CTA state.

## **Changelog**

CHANGELOG entry: Funding the Money account from the home-screen balance
card now opens the deposit flow directly instead of a bottom sheet, and
the card's button always shows "Earn" or "Add".

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MUSD-913
Refs: https://consensyssoftware.atlassian.net/browse/MUSD-935

## **Manual testing steps**

```gherkin
Feature: Money home-card funding

  Scenario: User holding mUSD taps the home-card CTA
    Given the user holds mUSD on at least one supported chain
    When the user taps the funding CTA on the Money balance card
    Then the MM Pay deposit screen opens with addMusd intent and their highest-balance mUSD token preselected
    And no funding bottom sheet is shown

  Scenario: User with no mUSD taps the home-card CTA
    Given the user holds no mUSD
    When the user taps the funding CTA on the Money balance card
    Then the Ramp Buy flow opens for adding mUSD
    And no funding bottom sheet is shown

  Scenario: CTA never shows "Get Started"
    Given a new user with a zero Money balance
    Then the card CTA renders as "Earn" (never "Get Started")
```

## **Screenshots/Recordings**

### **Before**

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

### **After**

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


https://github.com/user-attachments/assets/2a4f13ce-062b-4661-b7b9-c29e31de4902


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

- [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**
> Changes wallet-home funding navigation and deposit/Ramp entry points;
mistakes could send users to the wrong flow, though logic is centralized
and well covered by tests.
> 
> **Overview**
> The wallet home **Money balance card** no longer opens the add-money
bottom sheet or sends new users to Money home via a **Get started** CTA.
**Add** and **Earn** both call shared **`routeAddMoney`** from the new
**`useMoneyAccountAddRouting`** hook—the same routing other Money entry
points can use.
> 
> That hook chooses the path from mUSD holdings: with mUSD it starts
deposit via **`initiateDeposit`** (`addMusd`, highest per-chain balance
preselected); without mUSD it opens Ramp **Buy** for the mapped mUSD
asset. Button analytics now report **`ramp_buy`** or **`money_deposit`**
instead of the add-money sheet. Empty/new-user UI still shows **Earn**
(including when the home onboarding stepper is visible); only the
container test ID differs for unseen onboarding.
> 
> Tests cover the hook’s branching and updated card navigation/analytics
behavior.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
5571f23. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Feature Flag Registry Drift Report

Feature flag drift was detected between E2E tests and production.

Download the [`drift-report`
artifact](https://github.com/MetaMask/metamask-mobile/actions/runs/26793563675)
for the full report.

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Ramon Acitores <ramon.acitores@consensys.net>
Co-authored-by: Ramon AC <36987446+racitores@users.noreply.github.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 blocks the PR
check.

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

## **Description**

Fix token selection in withdraw money account page.

## **Changelog**

<!-- mms-check: type=changelog required=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/CONF-1510

## **Manual testing steps**
NA

## **Screenshots/Recordings**
NA

## **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**
> Small, localized change to default chain ID for one transaction type
in the confirmation pay-with flow, with tests updated.
> 
> **Overview**
> Fixes **money account withdraw** confirmation so the pay-with flow
defaults to **mUSD on Monad** instead of mUSD on **Ethereum mainnet**.
> 
> `resolvePreferredPayToken` now returns `CHAIN_IDS.MONAD` for
`moneyAccountWithdraw` when no override is set, aligning the
preferred-token row in the pay-with sheet with the withdraw-default
asset. Unit tests for `transaction-pay` and `usePayWithCryptoSection`
were updated to match.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
1c8d041. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@pull pull Bot locked and limited conversation to collaborators Jun 11, 2026
@pull pull Bot added the ⤵️ pull label Jun 11, 2026
@pull
pull Bot merged commit 782493c into Reality2byte:main Jun 11, 2026
0 of 9 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.