Skip to content

[pull] main from MetaMask:main#587

Merged
pull[bot] merged 11 commits intoReality2byte:mainfrom
MetaMask:main
Mar 9, 2026
Merged

[pull] main from MetaMask:main#587
pull[bot] merged 11 commits intoReality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Mar 9, 2026

See Commits and Changes for more details.


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

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

gantunesr and others added 11 commits March 9, 2026 13:27
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

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

Removes complete usage of the selector
`selectMultichainAccountsState1Enabled`.

## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MUL-1471

## **Manual testing steps**

Not applicable

## **Screenshots/Recordings**

Not applicable

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Removes feature-flag gating and the legacy `AccountNetworkRow`
UI/navigation path, which could change the switch-account modal behavior
and navigation flow. Risk is limited to UI/UX and modal routing (no
sensitive data/auth logic touched).
> 
> **Overview**
> **Removes the multichain accounts “state 1” flag path.** Deletes
`selectMultichainAccountsState1Enabled` and its unit tests, leaving only
the state-2 selector.
> 
> **Simplifies the switch-account-type modal row UI.**
`AccountNetworkRow` now always renders the switch-based layout (dropping
the legacy avatar/button variant), removes the conditional navigation to
`Routes.WALLET_VIEW`, and updates tests/styles accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
79499fe. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Changes in title and token hero section of confirmation page for
transfers (including send).

## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes: MetaMask/MetaMask-planning#7046

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**
<img width="391" height="849" alt="Screenshot 2026-03-04 at 9 04 51 PM"
src="https://github.com/user-attachments/assets/150c2888-7261-4346-b45d-7bf9a735f27c"
/>

<img width="393" height="847" alt="Screenshot 2026-03-04 at 9 35 48 PM"
src="https://github.com/user-attachments/assets/c6fc48b9-d4f2-40cd-8be6-ec1734dc4918"
/>

<img width="393" height="854" alt="Screenshot 2026-03-06 at 2 09 58 PM"
src="https://github.com/user-attachments/assets/f152ff50-fb9f-4021-ac23-235539fdb7e1"
/>

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because it changes the transaction confirmation UI (title
visibility and hero layout) in a critical user flow, which could affect
clarity or regress rendering across states (loading/skeleton, token vs
NFT). No signing or transaction data logic is modified.
> 
> **Overview**
> **Transfer confirmation header UI is redesigned.** Transfer
confirmations now render `HeroRow` in a new `layout="horizontal"` mode
that shows a localized **“Sending”** label with left-aligned details and
the asset icon/badge on the right, including matching horizontal
skeleton states.
> 
> **Title behavior is simplified for transfers.** The transfer flow sets
an empty navbar title and `Title` no longer renders a “Transfer request”
title (and avoids rendering any fallback title while transaction
metadata is still loading). Token/NFT hero components and the token
avatar-with-network-badge were updated to support the new layout
(including configurable avatar size and tooltip behavior for rounded
amounts), with tests and the new `confirm.label.sending` locale string
added.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f656955. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Amanda Yeoh <amanda.yeoh@consensys.net>
## Summary

Mobile counterpart to
[`va-mmcx-rewards#470`](consensys-vertical-apps/va-mmcx-rewards#470),
built on top of
[`#27108`](#27108).

- **Types**: adds `CampaignParticipantStatusDto` (`{ optedIn: boolean
}`) and `CampaignParticipantStatusState` to `types.ts`; adds new state
field `campaignParticipantStatus` to `RewardsControllerState`
- **Data service**: `optInToCampaign(subscriptionId, campaignId)` →
`POST /campaigns/:id/opt-in`;
`getCampaignParticipantStatus(subscriptionId, campaignId)` → `GET
/campaigns/:campaignId/status`
- **Controller**: `optInToCampaign` (no cache, feature-flag gated);
`getCampaignParticipantStatus` (5-min cache via `wrapWithCache`,
feature-flag gated)
- **Messenger**: both new service actions delegated through
`rewards-controller-messenger`
- **Hooks**:
- `useOptInToCampaign` — mutation hook, returns `null` when flag off or
no subscription
- `useGetCampaignParticipantStatus(campaignId)` — fetch-on-mount hook,
returns `null` status when flag off

Both hooks short-circuit on the `rewardsCampaignsEnabled` remote feature
flag.

## Test plan

- [x] `useOptInToCampaign.test.ts` — 5 tests (flag disabled, missing
sub, success, error, clear error)
- [x] `useGetCampaignParticipantStatus.test.ts` — 4 tests (flag
disabled, success, error, refetch)
- [x] `RewardsController.test.ts` — 3 state-metadata snapshots updated
(679 tests pass)
- [x] `util/logs/index.test.ts` — state-log snapshot updated
- [x] Prettier + ESLint clean

CHANGELOG entry: feat(rewards): add campaign opt-in and participant
status hooks/controller actions

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Adds new rewards API surface area (opt-in + status) with persisted
controller state and caching/event invalidation, which could affect data
freshness and state migrations. Risk is mitigated by feature-flag gating
and comprehensive unit tests/snapshots.
> 
> **Overview**
> **Adds campaign opt-in + participant status support under the
campaigns rewards feature flag.** This introduces
`RewardsController:optInToCampaign` and
`RewardsController:getCampaignParticipantStatus`, backed by new
`RewardsDataService` endpoints (`POST /wr/campaigns/:id/opt-in`, `GET
/campaigns/:id/status`).
> 
> **Adds cached participant-status state and invalidation.**
`RewardsController` now persists a `campaignParticipantStatus` cache
(5-minute TTL) and publishes a new `RewardsController:campaignOptedIn`
event on successful opt-in to invalidate cached status and trigger
refetch.
> 
> **Exposes new UI hooks with tests.** Adds `useOptInToCampaign`
(mutation w/ loading + error state) and
`useGetCampaignParticipantStatus` (fetch-on-mount + manual refetch +
event-driven refetch), plus updates snapshots/fixtures and removes a
previously-added concurrent-fetch test in `useRewardCampaigns.test.ts`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ea0c01f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=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 the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

The `Metrics Opt In` and `Metrics Opt Out` events
(`ANALYTICS_PREFERENCE_SELECTED`, `METRICS_OPT_OUT`) currently fire with
empty properties, making it difficult to distinguish wallet creation vs
import for opt-out users — where this is the only event that reaches
Segment

This PR adds the `account_type` property (`metamask`, `imported`,
`metamask_google`, `metamask_apple`) to these events, consistent with
all other onboarding events

* Jira: https://consensyssoftware.atlassian.net/browse/TO-566

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

## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: account_type in Metrics Opt In/Out events

  Scenario: user opts out of metrics during new wallet onboarding
    Given user has tapped "Create a new wallet" and completed wallet setup

    When user unchecks "Basic usage data" on the MetaMetrics consent screen and taps "Continue"
    Then METRICS_OPT_OUT and ANALYTICS_PREFERENCE_SELECTED events fire with account_type: "metamask"

  Scenario: user opts out of metrics during SRP import onboarding
    Given user has tapped "Import using Secret Recovery Phrase" and completed SRP import

    When user unchecks "Basic usage data" on the MetaMetrics consent screen and taps "Continue"
    Then METRICS_OPT_OUT and ANALYTICS_PREFERENCE_SELECTED events fire with account_type: "imported"

 ```

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: changes only add an optional `account_type` property to analytics events and thread a new onboarding Redux field through navigation; main risk is minor event-schema/attribution changes if the value is missing or incorrect.
> 
> **Overview**
> **Adds `account_type` to MetaMetrics consent events.** `OptinMetrics` and the Settings MetaMetrics toggle now attach an optional `account_type` property to `ANALYTICS_PREFERENCE_SELECTED` and `METRICS_OPT_OUT`.
> 
> **Introduces onboarding account-type state and propagation.** Adds `setAccountType`/`SET_ACCOUNT_TYPE`, stores `accountType` in the onboarding reducer with a selector, sets it during create/import/social-login start, and also passes `accountType` as a route param when navigating to `OptinMetrics` from backup/import flows.
> 
> **Tests updated/added** to cover the new action/reducer/selector behavior and verify `account_type` is included (or omitted when not provided) in tracked events.
> 
> <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 02e9f9f. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…27193)

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

## **Description**

Reorders the perps and Market Insights sections on the token details
screen so the layout is stable regardless of position state.
1. When a user has an open perps position, the position card now appears
directly below the balance (above Market Insights), giving active trades
priority.
2. When there is no position, the discovery/promotional banner renders
below Market Insights instead. This means

Market Insights always stays in the same place, meaning no layout shifts
as perps state changes. The discovery banner is demoted to a secondary
position so it never pushes informational content down.

<img height="800" alt="Simulator Screenshot - iPhone 16e - 2026-03-09 at
11 37 57"
src="https://github.com/user-attachments/assets/5cb5a681-8b24-4635-ac03-27b966ccc1d8"
/>
<img height="800" alt="Simulator Screenshot - iPhone 16e - 2026-03-09 at
11 38 26"
src="https://github.com/user-attachments/assets/6536ee13-2beb-4c6e-a8f4-da5e386b76cb"
/>


## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UI/layout-only change that reorders Perps components and
adjusts spacing; main risk is visual regression on the token details
screen when Perps position/loading states change.
> 
> **Overview**
> **Token details layout is reordered to be stable regardless of Perps
position state.** When a Perps position exists, the `PerpsPositionCard`
now renders above the Market Insights entry card; when no position
exists, the `PerpsDiscoveryBanner` renders below Market Insights.
> 
> This introduces a shared `showPerpsSection` guard to centralize Perps
render conditions and updates unit tests to mock
`usePerpsPositionForAsset` and assert the new ordering/visibility
behavior. Separately, the Market Insights entry card adds bottom spacing
(`mb-4`) for improved visual separation.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
08cf77e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Move `ScamWarningModal` and `RemoveTokenBottomSheet` outside of the
inner `Box` container in `TokensSection` so they are siblings of the
section content rather than children. This fixes spacing issues caused
by the modals contributing to the layout flow inside the tokens section
container.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

N/A

## **Manual testing steps**

```gherkin
Feature: Homepage Tokens Section spacing

  Scenario: user views the Tokens section on the Homepage
    Given the user has the Homepage with Tokens section enabled

    When user scrolls to the Tokens section
    Then the section spacing is correct with no extra gaps caused by modals

  Scenario: user long-presses a token to remove it
    Given the user is viewing the Tokens section

    When user long-presses on a token row
    Then the remove token bottom sheet appears correctly
```

## **Screenshots/Recordings**

### **Before**

<img width="300" alt="before_tss"
src="https://github.com/user-attachments/assets/109890ef-cb36-4d48-92b3-94f0cda027f5"
/>

### **After**

<img width="300" alt="after_tss"
src="https://github.com/user-attachments/assets/c56ef745-2a20-4117-920a-1b8bff5cf3c3"
/>

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UI-only change that only adjusts component hierarchy to avoid
unintended spacing; no business logic, state, or data-flow changes.
> 
> **Overview**
> Fixes unwanted gaps in the Homepage Tokens section by rendering
`ScamWarningModal` and `RemoveTokenBottomSheet` *outside* the inner
`Box` (as siblings of the section content) so they no longer participate
in the section’s layout flow.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
82f08d9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…26757)

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

## **Description**

Replaces the manual "clone connect-monorepo and build locally" workflow
with automated APK fetching from GitHub Releases, and wires up the
playground APK for BrowserStack cloud E2E runs.

#### What

- **Fetch script** (`scripts/fetch-rn-playground-apk.sh`):
- Downloads `rn-playground-<version>.apk` from connect-monorepo GitHub
Releases
- Supports version pinning via `--version` flag or
`RN_PLAYGROUND_APK_VERSION` env var
  - Defaults to latest release; saves to `./tmp/rn-playground.apk`
  - Uses `GITHUB_TOKEN` when available to avoid API rate limits

- **Updated APK resolution** (`tests/performance/mm-connect/utils.js`):
- `ensurePlaygroundInstalled()` now checks three locations in priority
order:
    1. `RN_PLAYGROUND_APK_PATH` env var (explicit override)
    2. `./tmp/rn-playground.apk` (downloaded by the fetch script)
3. Sibling `../connect-monorepo/...` local build (original path, still
works)
  - Error messages guide users to the fetch script or local build

- **BrowserStack integration** (Appwright patch + CI workflow):
- Added `otherApps` support to the Appwright yarn patch: when
`BROWSERSTACK_RN_PLAYGROUND_URL` is set, it's included in
`bstack:options.otherApps`, telling BrowserStack to pre-install the
playground alongside the wallet
- New `fetch-rn-playground-apk` job in `run-performance-e2e.yml`:
downloads the APK from GitHub Releases → uploads to BrowserStack →
passes `bs://` URL to the mm-connect test runner
- `performance-test-runner.yml` accepts optional
`browserstack_playground_url` input and sets it in the test environment

#### Why

The multichain RN connect E2E tests need two native apps on the device —
the MetaMask wallet and the playground dApp. Previously, getting the
playground APK required manual steps that couldn't run in CI. This
change makes the full mm-connect test suite runnable in both local and
BrowserStack CI environments without manual intervention.

#### BrowserStack approach

After evaluating three options (upload in connect-monorepo CI, upload in
metamask-mobile CI, hybrid), the implementation uses **upload in
metamask-mobile CI**: the APK is fetched from GitHub Releases and
uploaded to BrowserStack per test run. This keeps BrowserStack
credentials scoped to metamask-mobile, avoids app expiry issues, and
follows the same pattern used for the wallet APK via Bitrise.

### Files changed

| File | Change |
|------|--------|
| `scripts/fetch-rn-playground-apk.sh` | New script to download APK from
GitHub Releases |
| `tests/performance/mm-connect/utils.js` | Multi-path APK resolution
with fallback chain |
| `tests/performance/mm-connect/README.md` | "Download from Releases" as
primary option, CI/BrowserStack docs |
| `.yarn/patches/appwright-npm-0.1.45-*.patch` | `otherApps` in
`bstack:options` from env var |
| `.github/workflows/run-performance-e2e.yml` | New
`fetch-rn-playground-apk` job |
| `.github/workflows/performance-test-runner.yml` | Optional
`browserstack_playground_url` input |


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

## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/WAPI-1126

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because it changes CI workflow orchestration and
BrowserStack/Appium capabilities via a patched `appwright`, which could
affect stability or configuration of performance E2E runs.
> 
> **Overview**
> Enables fully automated `mm-connect` performance E2E runs by fetching
the React Native playground APK from `connect-monorepo` GitHub Releases,
uploading it to BrowserStack, and passing the resulting `bs://` URL into
the reusable `performance-test-runner` workflow.
> 
> Updates the `mm-connect` local setup to resolve the playground APK
from `RN_PLAYGROUND_APK_PATH`, `./tmp/rn-playground.apk`, or the legacy
sibling build path, and refreshes docs accordingly. The patched
`appwright` now supports `otherApps` via
`BROWSERSTACK_RN_PLAYGROUND_URL`, allows disabling BrowserStack Local,
uses a unified `BROWSERSTACK_BUILD_NAME`, and skips BrowserStack video
download when `DISABLE_VIDEO_DOWNLOAD=true` (plus additional
Appium/BrowserStack capability tweaks).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
26d2eec. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Alex Donesky <adonesky@gmail.com>
## **Description**

Fixes several layout and UX issues on the Ramps Order Details screen:

1. **Info icon placement**: Moved the info icon inline at the end of the
status description text (with baseline alignment via `translateY`)
instead of rendering it separately.
2. **Status description padding & centering**: Added horizontal padding
and `text-center` so the description text wraps correctly within bounds.
3. **Footer pinned to bottom**: The status description and close button
are now pushed to the bottom of the screen using `mt-auto` (with `flex:
1` + `flexGrow: 1` on the parent ScrollView) so the layout looks correct
regardless of content height.
4. **Strip redundant order prefix**: For processing orders, the "Your
order for X is processing." prefix is stripped from the API-provided
`statusDescription`, leaving only the actionable info (e.g., "Card
purchases may take a few minutes to complete.").
5. **Toast bottom offset**: Added `customBottomOffset: 32` to the
pending-order toast so it doesn't overlap the status description text on
the Order Details screen.
6. **Processing info modal text centering**: Centered the
`statusDescription` text in the `ProcessingInfoModal` bottom sheet so it
aligns visually with the full-width support button below it.

## **Changelog**

CHANGELOG entry: Fixed layout issues in Ramp Order Details — inline info
icon, centered status text, sticky footer, stripped redundant order
prefix, adjusted toast offset, and centered text in processing info
modal.

## **Related issues**

Refs:
[TRAM-3318](https://consensyssoftware.atlassian.net/browse/TRAM-3318)

## **Manual testing steps**

```gherkin
Feature: Ramp order details layout improvements

  Scenario: processing order shows trimmed status description with inline icon
    Given the user opens the Order Details screen for a processing ramp order

    When the status description is displayed at the bottom
    Then the "Your order for X is processing." prefix is removed
    And only the actionable text (e.g. "Card purchases may take a few minutes to complete.") is shown
    And the info icon appears inline at the end of the text
    And the text is centered and properly padded

  Scenario: failed order keeps full status description
    Given the user opens the Order Details screen for a failed ramp order

    When the status description is displayed
    Then the full error message is shown without any prefix stripping
    And the info icon appears inline at the end of the text

  Scenario: close button and description pinned to bottom
    Given the user opens the Order Details screen

    When the screen is displayed with showCloseButton=true
    Then the status description and close button are pinned to the bottom
    And the close button works correctly

  Scenario: pending toast does not overlap status description's last line
    Given the user is on the Order Details screen for a processing order
    And the pending toast is visible

    When the toast appears
    Then the toast does not overlap the status description's last line text

  Scenario: processing info modal shows centered text
    Given the user taps the info icon on the Order Details screen

    When the processing info modal opens
    Then the status description text is centered
    And the "Go to [provider] support page" button is full width below it
```

## **Screenshots/Recordings**

### **Before**

<img width="435" height="827" alt="Screenshot 2026-03-05 204015"
src="https://github.com/user-attachments/assets/83f61887-5dd7-4a15-9ff6-be599408640a"
/>

<img width="355" height="730" alt="Screenshot 2026-03-08 122843"
src="https://github.com/user-attachments/assets/40b35b9f-a2c5-4783-920a-b6509235b68f"
/>




https://github.com/user-attachments/assets/ba9a1baa-e162-4ff3-a007-a967ca054e2f





### **After**

<img width="346" height="416" alt="Screenshot 2026-03-05 193156"
src="https://github.com/user-attachments/assets/22f24a43-aee9-42fe-b8dd-3757be1ff1f2"
/>

<img width="353" height="695" alt="Screenshot 2026-03-08 122440"
src="https://github.com/user-attachments/assets/a0bf0a6b-9575-41dd-838c-a69171c2ea16"
/>



https://github.com/user-attachments/assets/cd733f75-2d2d-489a-8092-56a25fd48f7e



## **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
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

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



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Mostly UI/layout tweaks, but it also adds conditional string
stripping/regex on `statusDescription` for pending/processing orders
which could alter user-visible messaging if provider text formats
change.
> 
> **Overview**
> Improves the Ramp V2 Order Details UX by **centering and better
wrapping** the status description, moving the info icon **inline** with
baseline alignment, and making the footer area (status + optional close
button) **stick to the bottom** via `flex`/`flexGrow` adjustments.
> 
> For pending/processing statuses, trims the redundant "Your order … is
processing" prefix from `statusDescription`, and adds a
`customBottomOffset` to the pending toast to avoid overlapping the
footer; the Processing Info modal’s description text is also centered.
Snapshot tests are updated accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f4172b6. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…MarketDetails (#26872)

## Summary
- Reorders `getMarketDetails()` to fetch the event from API first, then
inspect it with `getEventLeague()` to determine if it's a sports event
- Only loads `TeamsCache` and applies `GameCache` overlay for actual
sports events
- Non-sports market details (and non-sports highlighted markets via
`getMarketsByIds`) skip the sports pipeline entirely

## Test plan
- [x] Updated existing tests to mock `getEventLeague` for sports event
detection
- [x] Added new test verifying non-sports events skip TeamsCache and
GameCache even when leagues are configured
- [x] All 399 PolymarketProvider tests pass

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes conditional logic for applying `TeamsCache`/`GameCache`
overlays in a user-facing market-details path; incorrect event detection
could cause missing sports overlays or skipped team loading.
> 
> **Overview**
> **Sports overlays in `getMarketDetails` are now event-driven.** The
provider fetches the Gamma event first, then uses
`isLiveSportsEvent(event, enabledLeagues)` to decide whether to load
`TeamsCache`, provide a `teamLookup` to parsing, and apply the
`GameCache` overlay.
> 
> This prevents non-sports markets from triggering the sports pipeline
even when `liveSportsLeagues` is configured. Tests were updated to mock
`isLiveSportsEvent` and add coverage ensuring non-sports events skip
`TeamsCache`/`GameCache`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0bc0605. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

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

## **Description**

This PR scopes `TokenSelectorItem` updates to sizing and color hierarchy
only in the Bridge asset selector.

Changes included:
- Set ticker text to `BodyMDMedium` (16sp).
- Set token balance text to `BodyMDMedium` (16sp) with default text
color.
- Set fiat balance text to `BodyMD` (16sp) with alternative text color.

## **Changelog**

CHANGELOG entry: Updated Bridge token selector balance sizing and color
hierarchy.

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: Bridge token selector balance sizing and color hierarchy

  Scenario: user views token selector rows
    Given the user opens the Bridge token selector
    When a token row is rendered with both token and fiat balances
    Then ticker text is shown in 16sp medium weight
    And token balance is shown in 16sp medium weight with default text color
    And fiat balance is shown in 16sp regular weight with alternative text color
```

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk UI-only change adjusting text variants/colors for token and
fiat balances in the Bridge token selector; no business logic, data, or
security behavior changes.
> 
> **Overview**
> Updates `TokenSelectorItem` balance presentation to better reflect a
primary/secondary hierarchy in the Bridge asset selector.
> 
> The token symbol and right-side token balance are now rendered with
`BodyMDMedium` and default text color, while the fiat balance display is
rendered with `BodyMD` and alternative text color (including its
non-loading state), making fiat visually secondary.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6405330. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

This PR is the Ramp-only split of the `color-no-hex` batch work,
extracted from the original umbrella PR #26651.

Scope:
- Ramp files only (`app/components/UI/Ramp/**`)
- temporary eslint rollout override for
`app/components/UI/Ramp/**/*.{js,jsx,ts,tsx}`
- includes replacing straightforward mock color suppressions in
`DepositProgressBar` test with `mockTheme`

Reference PR: #26651

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: color-no-hex ramp batch

  Scenario: validate ramp lint and tests
    Given this branch is checked out
    When running eslint for Ramp scope
    Then there are no lint errors

    When running jest for Ramp scope with snapshot updates
    Then tests pass
```

## **Screenshots/Recordings**

### **Before**
N/A (test/lint/config updates only)

### **After**
N/A (test/lint/config updates only)

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: changes are limited to ESLint override scope and test-only
theme mocks/assertions, with no production logic changes aside from a
local lint-disable comment on an SVG component.
> 
> **Overview**
> **Enables `@metamask/design-tokens/color-no-hex` enforcement for
`app/components/UI/Ramp/**`** via an ESLint override, as part of the
incremental rollout.
> 
> Updates multiple Ramp tests to stop using hardcoded hex colors by
reusing `util/theme`'s `mockTheme` (including `DepositProgressBar`,
`DepositTextField`, `generateThemeParameters`, `PaymentMethodSelector`,
`BankDetails`, and `useTransakRouting`), and adds a targeted file-level
lint disable in `ShapesBackgroundAnimation` where the SVG uses fixed
brand colors without token equivalents.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ff93cb5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@pull pull Bot locked and limited conversation to collaborators Mar 9, 2026
@pull pull Bot added the ⤵️ pull label Mar 9, 2026
@pull pull Bot merged commit 1242530 into Reality2byte:main Mar 9, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.