Skip to content

chore: sync stable into release/7.82.0#31674

Open
metamaskbotv2[bot] wants to merge 55 commits into
release/7.82.0from
stable-sync-release-7.82.0
Open

chore: sync stable into release/7.82.0#31674
metamaskbotv2[bot] wants to merge 55 commits into
release/7.82.0from
stable-sync-release-7.82.0

Conversation

@metamaskbotv2

@metamaskbotv2 metamaskbotv2 Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR syncs the latest changes from stable into release/7.82.0.

Why is this needed?

A release branch (release/7.81.0) was merged into stable. This PR brings those changes (hotfixes, etc.) into release/7.82.0.

Action Required

Please review and resolve any merge conflicts manually.

If there are conflicts, they will appear in this PR. Resolve them to ensure the release branch has all the latest fixes from stable.

metamaskbot and others added 30 commits June 4, 2026 21:15
…Android cp-7.81.0 (#31106)

- fix: wallet home onboarding Rive crash on Android cp-7.81.0 (#31042)

## **Description**

Fixes a fatal native crash on Android originating in
`rive-react-native`'s checklist Rive animation on the wallet home
onboarding screen. Affects ~2.3K production users

Root cause was in the `.riv` asset not being fully aligned with the
code. The wallet home checklist Rive `onboard_checklist_v05.riv` had
inconsistent State Machine inputs across its three artboards:

- `01_Add_Funds` and `02_First_Trade` were missing the `Main` trigger
input that the code fires via `fireState('State Machine 1', 'Main')`.

When the code fired a name that didn't match, Rive threw
`StateMachineInputException`. `rive-react-native`'s native code doesn't
clear the pending Java exception before its next JNI call, violating
ART's JNI rules and aborting the process (`SIGABRT` / `SIGSEGV`
depending on device).

Fix:
- Added missing `Main` trigger inputs to `01_Add_Funds` and
`02_First_Trade`, wired to the `Intro → Main` transition.
- Renamed `"Outro "` to `"Outro"` on `03_Notifications`.
- Re-exported as `onboard_checklist_v06.riv`.
- Bumped the import in `WalletHomeOnboardingSteps.tsx` from v05 to v06.

Verified locally: previously-crashing flows on emulator and arm64
physical device no longer crash, and the ~0.25s animation flicker
observed on flagship devices is also gone.

## **Changelog**

CHANGELOG entry: Fixed a native crash on Android affecting users on the
wallet home onboarding screen.

## **Related issues**

Fixes: #31103
#31103

## **Manual testing steps**

```gherkin
Feature: Wallet home onboarding checklist Rive animation

  Scenario: User steps through the onboarding checklist
    Given the user has completed primary onboarding on a fresh install
    And the wallet home onboarding checklist is visible
    When the user taps Skip or Continue through fund / trade / notifications steps
    Then the checklist animation plays intro → main → outro on each step
    And the app does not crash

  Scenario: User navigates away from a step and returns
    Given the user is on the trade or notifications step
    When the user taps the Primary button and navigates to the destination screen
    And the user returns to the wallet home screen
    Then the checklist Rive resumes correctly
    And the app does not crash
```

## **Screenshots/Recordings**



https://github.com/user-attachments/assets/0d84b394-10f3-485f-8689-ad847111ee65

### **Before**




https://github.com/user-attachments/assets/bc562dc8-305c-4e61-a1be-472d68e675aa


### **After**



https://github.com/user-attachments/assets/0d84b394-10f3-485f-8689-ad847111ee65

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

<!--
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**
> Binary animation asset plus a single import path change; no auth,
payments, or business-logic changes beyond fixing Rive input names.
> 
> **Overview**
> Fixes a **production Android native crash** on wallet home
post-onboarding when the checklist Rive animation runs. The app already
drives **`Main`** and **`Outro`** on **`State Machine 1`** via
`fireState`; **`onboard_checklist_v05.riv`** was out of sync (missing
**`Main`** on the fund and trade artboards, and a mismatched outro input
name on notifications), which led to `StateMachineInputException` and a
fatal JNI abort in `rive-react-native`.
> 
> The change **re-exports the animation as `onboard_checklist_v06.riv`**
with aligned triggers and transitions, and **points
`WalletHomeOnboardingSteps` at v06** instead of v05. No change to the
checklist flow logic beyond the asset swap.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
1945d4f. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[bdce2e9](bdce2e9)

Co-authored-by: Vince Howard <vincenguyenhoward@gmail.com>
…o crypto up/down markets cp-7.81.0 (#31112)

- feat(predict): add Ethereum accent color to crypto up/down markets
cp-7.81.0 (#31029)

## **Description**

Maps the `ETH` symbol to `#5E6DB7` in both the series card
(`PredictCryptoUpDownMarketCard`) and the details screen
(`PredictCryptoUpDownDetails`) so Ethereum up/down markets render with a
distinct accent — chart line, sparkline, badge, and current-price text —
instead of falling back to the default amber.

Symbol resolution was already in place via `getCryptoSymbol()`
(`ethereum` tag + `eth-` slug prefix), so only the two color lookup
tables (`CRYPTO_SYMBOL_TO_ACCENT_COLOR` on the details screen,
`CRYPTO_ACCENT_BY_SYMBOL` on the card) needed extending. BTC keeps its
orange accent and any unmapped symbol continues to fall back to the
default amber.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: PRED-941

## **Manual testing steps**

```gherkin
Feature: Predict Ethereum up/down accent color

  Scenario: user views an Ethereum up/down market card on the feed
    Given the predict up/down feature flag is enabled
    And an Ethereum up/down market is available in the feed

    When the user scrolls to the Ethereum market card
    Then the card's sparkline and accent elements render in the Ethereum accent (#5E6DB7)
    And BTC up/down cards continue to render in the BTC orange accent
    And any unmapped crypto up/down card falls back to the default amber accent

  Scenario: user opens the Ethereum up/down details screen
    Given the predict up/down feature flag is enabled
    And an Ethereum up/down market is available

    When the user taps the Ethereum market card and opens the details screen
    Then the chart line, "Current price" label, and current price value render in the Ethereum accent (#5E6DB7)
    And opening a BTC up/down market still renders in the BTC orange accent
```

## **Screenshots/Recordings**

### **Before**

<!-- Not provided — Ethereum up/down markets previously fell back to the
default amber accent (`rgb(245, 158, 11)`), identical to any unmapped
symbol. -->

### **After**

<img width="370" height="308" alt="Screenshot 2026-06-03 at 8 42 17 PM"

src="https://github.com/user-attachments/assets/20ccd606-46d2-4b46-9ade-e3314f4dc6a7"
/>

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

Not applicable; static color constant addition only.

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

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

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

For performance guidelines and tooling, see the [Performance

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Static UI color constants and unit tests only; no auth, data, or
trading logic changes.
> 
> **Overview**
> Adds **Ethereum** (`rgb(94, 109, 183)` / `#5E6DB7`) to the crypto
up/down accent color maps on the **feed card**
(`CRYPTO_ACCENT_BY_SYMBOL`) and **details screen**
(`CRYPTO_SYMBOL_TO_ACCENT_COLOR`), so ETH markets use a distinct purple
accent instead of the default amber. **BTC** orange and the **default**
fallback are unchanged.
> 
> Details tests now assert the chart receives the correct `color` for
BTC, ETH, and unmapped symbols (mock chart exposes `color` in
`accessibilityLabel`; target-price parsing was adjusted for the extra
label segment).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
2290913. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[02bdd66](02bdd66)

Co-authored-by: hunty <hunter.goodreau@consensys.net>
…tifications to prevent large preview images (#31121)

- fix: disable link unfurling in Slack RC notifications to prevent large
preview images (#31116)

<!--
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 -->
Disable link unfurling in Slack RC notifications to prevent large
preview images
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

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

<!--
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 -->
TestFlight link preview with large image displayed in the Slack RC build
notification.
Fixes: disables unfurl

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->
N/A — <reason>

## **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**
N/A
<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

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

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

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

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding

Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling

guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

- [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).
- [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**
> Single optional API flags on an internal release-notification script
with no app or security impact.
> 
> **Overview**
> RC build Slack notifications now pass **`unfurl_links: false`** and
**`unfurl_media: false`** on `chat.postMessage`, so Slack stops
expanding download, GitHub, and pipeline URLs into large link previews
in release channels.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
3448f28. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[1bc6039](1bc6039)

Co-authored-by: sleepytanya <104780023+sleepytanya@users.noreply.github.com>
…y without iOS modal presentation (#31152)

chore(runway): cherry-pick fix(card): cp-7.81.0 restore slide-up entry without iOS modal presentation
…-7.81.0 (#31158)

- chore: cleanup perps top movers buttons cp-7.81.0 (#31147)

## **Description**

Makes Gainers/Loser buttons larger and more accessible

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: css bug

## **Manual testing steps**

N/A

## **Screenshots/Recordings**

<img width="428" height="260" alt="Screenshot 2026-06-05 at 6 54 09 AM"

src="https://github.com/user-attachments/assets/a9f4a656-a388-4ba5-8bc9-870bbe369fc7"
/>

## **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**
> Cosmetic Tailwind class changes on a Perps home UI toggle with no
logic, data, or auth impact.
> 
> **Overview**
> Updates the **Gainers / Losers** toggle styling in
`PerpsTopMoversSection` so the pills are easier to tap and read.
> 
> `TogglePill` now uses **`rounded-lg`** instead of **`rounded-xl`**,
adds **`justify-center`** and **`py-1`** for vertical padding and
centered label alignment—matching the PR goal of larger, more accessible
buttons.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
52ad854. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[b400262](b400262)

Co-authored-by: Nick Gambino <nicholas.gambino@consensys.net>
… user-enabled networks (#31154)

- feat: scope QuickBuy networks to user-enabled networks (#31092)

## **Description**

QuickBuy's "Pay with" / "Receive" screen was showing network pills (and
token rows) for **every** candidate network, including ones the user
never enabled (e.g. HyperEVM, Sei, Tempo). Some of those also rendered
as **"Unknown network"** because they aren't present in the user's
`NetworkController` state.

This PR scopes QuickBuy to the networks the user has actually enabled
and makes popular network names resolve to a readable label:

1. **Filter by enabled networks.** A new self-contained
`useNetworkEnabledPredicate` hook returns a `(chainId) => boolean`
predicate backed by `selectEVMEnabledNetworks` (hex) and
`selectNonEVMEnabledNetworks` (CAIP), branching on `isNonEvmChainId`.
It's applied at the token-options layer (`useSourceTokenOptions` and
`useSellDestTokenOptions`) so pills, token rows, and default selection
all stay consistent — disabled networks can't be implicitly selected.
2. **Readable fallback names.** `resolveNetworkDisplayName` now falls
back to the curated `NETWORK_TO_NAME_MAP` for EVM hex and `eip155` CAIP
chain IDs, so known popular networks (MegaETH, HyperEVM, …) show their
real name instead of "Unknown network".

The filtering lives in the hooks rather than the UI component, keeping
the existing `useIsNetworkEnabled` per-chain hook untouched.

## **Changelog**

CHANGELOG entry: Fixed QuickBuy showing networks the user hasn't enabled
and labeling some networks as "Unknown network".

## **Related issues**

Fixes: [TSA-617](https://consensyssoftware.atlassian.net/browse/TSA-617)
and [TSA-620](https://consensyssoftware.atlassian.net/browse/TSA-620)

## **Manual testing steps**

```gherkin
Feature: QuickBuy network scoping

  Scenario: Receive screen hides disabled networks
    Given a network such as Sei is not enabled
    When the user opens QuickBuy and views the "Receive" screen
    Then no pill or token row is shown for Sei

  Scenario: Enabling a network reveals it in QuickBuy
    Given the user enables Sei via the network selector
    When the user re-opens the QuickBuy "Receive" screen
    Then a pill and token rows for Sei are shown

  Scenario: Popular networks show a readable name
    Given MegaETH/HyperEVM are not configured in NetworkController
    When their pill is rendered
    Then the curated network name is shown instead of "Unknown network"
```

## **Screenshots/Recordings**

### **Before**

<img width="1170" height="2532" alt="image"

src="https://github.com/user-attachments/assets/73a6afd1-4c20-46ff-bfb7-5d3796252d45"
/>

### **After**

<img width="392" height="414" alt="image"

src="https://github.com/user-attachments/assets/bb4ff5b7-98fd-487f-b7cc-a0f62ab9fee5"
/>

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding

Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling

guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

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

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

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

For performance guidelines and tooling, see the [Performance

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> UI filtering and display-name fallbacks only; no auth, transactions,
or persistence changes beyond existing enablement selectors.
> 
> **Overview**
> QuickBuy **Pay with** / **Receive** lists now only include tokens on
networks the user has enabled, via a new `useNetworkEnabledPredicate`
hook wired into `useSourceTokenOptions` and `useSellDestTokenOptions` so
pills, rows, and defaults stay aligned.
> 
> **Network labels:** `resolveNetworkDisplayName` falls back to curated
`NETWORK_TO_NAME_MAP` (e.g. MegaETH, HyperEVM) when a chain isn’t in
`NetworkController` state, including `eip155` CAIP IDs.
`NETWORK_TO_NAME_MAP` build is guarded when `NETWORK_CHAIN_ID` is
undefined in tests so UI imports don’t throw at module load.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
ba0104a. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

[TSA-617]:

https://consensyssoftware.atlassian.net/browse/TSA-617?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

---------

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

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

Co-authored-by: Xavier Brochard <xavier.brochard@consensys.net>
Co-authored-by: Cursor <cursoragent@cursor.com>
…ctMarketHighlights cp-7.81.0 (#31161)

- feat(predict): support series ids in predictMarketHighlights cp-7.81.0
(#31044)

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

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

Extends the `predictMarketHighlights` remote feature flag to accept
series IDs in addition to market IDs, and renders series-resolved crypto
up/down highlights in horizontally-scrolling carousels via a new compact
card variant.

**Why**

Recurring crypto up/down markets (e.g. "BTC Up or Down — 5 Minutes")
expose a new market every N minutes. A market-ID pin in
`predictMarketHighlights` therefore goes stale within a single time slot
— once the market resolves, the pin disappears, and there is no way to
express "always pin the currently-live BTC Up/Down 5m market." Resolving
from a series at request time fixes this: the pin automatically rotates
to whatever slot is live when the feed is fetched.

**Schema change (additive, backward compatible)**

```ts
export interface PredictMarketHighlight {
  category: string;
  markets?: string[]; // was required, now optional
  series?: string[];  // NEW
}
```

- Existing LD flag values that only use `markets` continue to work
unchanged. Both fields are now optional; entries with neither are
skipped.
- The controller's highlight block fetches `getMarketsByIds(markets)`
and `getMarketSeries(seriesId)` in parallel via `Promise.all`, then
resolves each series response to its currently-live market via the
existing `findLiveMarket()` (with `findNearestMarket()` as a fallback
when no future market is in the fetch window).
- Resolved series markets pass through the same `status === 'open'`
filter and are marked with `isHighlighted: true`, identical to the
market-ID path.
- Order: market-ID highlights are prepended first, then series-resolved
highlights, then the regular feed. Existing flag values that only use
`markets` keep their original ordering. Dedupe is unified across both
paths so a market reachable via both `markets` and `series` appears
exactly once.

**Compact carousel variant**

`PredictCryptoUpDownMarketCard` now has two render variants, keyed off
the existing `isCarousel` prop that `PredictMarket` forwards to its
sibling cards (`PredictMarketSingle`, `PredictMarketMultiple`,
`PredictMarketSportCard`):

- **Full** (`isCarousel=false`, the default) — the existing sparkline +
target-line / target-price treatment used on `PredictFeed`,
`PredictHome`, the wallet home carousel, and search.
- **Compact** (`isCarousel=true`) — drops the sparkline and target
labels and switches to a `height: 100%` + flex-column + `justifyContent:
'space-between'` layout that mirrors `PredictMarketSingle` /
`PredictMarketMultiple` so the card sits flush with its neighbours in
`HorizontalCarousel`. This is the variant the 5 TrendingView carousel
tabs (Now, Macro, RWAs, Crypto, Sports) render for series-resolved
highlights.

The compact path also gates `useCryptoUpDownChartData` and
`useCryptoTargetPrice` with `enabled: !isCompact`, so the chart
historical fetch and live-price websocket subscription don't run for
cards that never display them.

**Resilience**

- Per-series fetch failures are caught locally with a `DevLogger.log`,
so one unhealthy series entry can't take down a healthy batch.
- The series fetch reuses the canonical `SERIES_MAX_EVENTS` (50) for
`limit`. The provider returns markets in `endDate ASC` order, and a fast
recurrence (5m) can produce ~12 past events inside the past buffer alone
— too low a limit would clip the live slot.
- `getMarketsByIds` keeps its existing fail-hard contract; the
previously misleading test `"handles getMarketsByIds failure
gracefully"` (which actually only tested an empty-array result) was
renamed accordingly, and a real rejection-propagation test was added.

**Test coverage**

- 8 new tests in `PredictController.test.ts` (live-market resolution,
mixed markets+series ordering, nearest-market fallback, empty-series
skip, closed-market status filter, throw-silent on single series,
partial-batch failure, dedupe across paths)
- 1 shape-passthrough test in `resolvePredictFeatureFlags.test.ts`
- 4 new tests in `PredictCryptoUpDownMarketCard.test.tsx` covering the
compact variant (sparkline not rendered, both chart queries gated with
`enabled: false`, compact skeleton renders, buy sheet still opens)
- All tests in the touched suites pass.

## **Changelog**

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

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

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

CHANGELOG entry: Added support for pinning the currently-live market of
a recurring series (e.g. BTC Up/Down 5m) via the
`predictMarketHighlights` remote feature flag.

## **Related issues**

Fixes: PRED-950

## **Manual testing steps**

Both scenarios assume the `predictMarketHighlights` LaunchDarkly
variation is updated to the new shape. The series ID `10684` corresponds
to the Polymarket Gamma `BTC Up/Down 5m` series (also hardcoded as
`BTC_UP_DOWN_5M_SERIES_ID` in
`app/components/UI/Predict/constants/btcUpDown5mSeries.ts`).

```gherkin
Feature: Series-id highlights in predictMarketHighlights

  Scenario: A series-id highlight resolves to the currently-live market on PredictFeed
    Given the predictMarketHighlights flag is set to
      """
      {
        "enabled": true,
        "minimumVersion": "7.63.0",
        "highlights": [
          { "category": "crypto", "series": ["10684"] }
        ]
      }
      """
    When the user opens the Predict tab and switches to the "Crypto" feed tab
    Then the currently-live BTC Up/Down 5m market is pinned at the top of the feed
    And the pin auto-rotates to the next live slot when the current one resolves
    And the card renders in the full variant (with sparkline + target labels)

  Scenario: A series-id highlight renders the compact variant in TrendingView carousels
    Given the same flag configuration as above
    When the user opens the Explore page and views the "Crypto" or "Now" tab carousel
    Then the BTC Up/Down series card IS pinned in the Explore carousel
    And it renders as the compact variant (no sparkline, same height as its neighbours)
    And no chart-history fetch or live-price websocket subscription is opened for that card

  Scenario: Existing market-id highlights are unaffected
    Given the predictMarketHighlights flag is set to
      """
      {
        "enabled": true,
        "highlights": [
          { "category": "trending", "markets": ["451614"] }
        ]
      }
      """
    When the user opens PredictFeed → Trending and Explore → Now
    Then market 451614 is pinned at the top on both surfaces (market-id path is unchanged)
```

## **Screenshots/Recordings**

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

### **Before**

N/A

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

### **After**

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

## **Pre-merge author checklist**

<!--
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**
> Feed ordering and highlight resolution now depend on series API
behavior and remote flag shape; carousel gating changes which data loads
on Explore surfaces.
> 
> **Overview**
> Adds optional **`series`** IDs to **`predictMarketHighlights`** so
recurring crypto up/down pins resolve to the **currently live** market
via **`getMarketSeries`** + **`findLiveMarket`** /
**`findNearestMarket`**, merged with existing market-ID highlights
(parallel fetch, dedupe, open-only, market IDs first).
> 
> **`PredictCryptoUpDownMarketCard`** now honors **`isCarousel`**: a
**compact** layout (no sparkline/target UI, full-height flex) and
**`enabled: false`** on chart/target hooks to avoid unused network work
in Explore carousels; full feed cards unchanged with **`enabled: true`**
on chart data.
> 
> Controller tests cover series resolution edge cases;
**`getMarketsByIds`** failures now **reject** instead of being
mislabeled as graceful handling.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
83f5c75. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[c32e24f](c32e24f)

Co-authored-by: hunty <hunter.goodreau@consensys.net>
…d purge seeded orders (#31229)

- fix(ramps): remove Navigation Dev Panel and purge seeded orders cp-7.81.0 (#31188)

<!--
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.
… with quote loader (#31238)

- fix(quick-buy): enable Buy CTA in lockstep with quote loader (#31218)

## **Description**

In the QuickBuy bottom sheet, the **Buy** button sometimes took longer
to become enabled than the amount-section quote loader took to
disappear. The user expects the CTA to become tappable as soon as the
quote completes.

**Reason for the change:** the loader and the Buy button were gated by
two conditions that drifted out of sync for one render. The loader is
driven by `isBlockingQuoteLoad` (gated by `isQuoteLoading`), which
clears the instant the fetch resolves. The button is gated by
`isConfirmDisabled`, which includes `isPendingQuoteRefresh` — and that
value was derived from `settledSourceTokenAmountRef`, a ref updated only
inside a post-commit `useEffect`. On the render where the quote arrived,
the loader hid but the ref had not caught up, and ref writes do not
schedule a re-render, so the CTA only re-enabled on the next unrelated
render (a redux tick, gas-estimate update, quote countdown, etc.) —
producing the variable lag.

**Solution:** replace the timing/effect-based "settled amount" tracking
with a synchronous derivation. A displayed quote is for the current
amount when the quote's own `srcTokenAmount` equals the requested amount
(the request is built with `calcTokenValue(sourceTokenAmount,
decimals).toFixed(0)` and the bridge echoes that exact value back).
`isPendingQuoteRefresh` now derives from this synchronous check, so
`isBlockingQuoteLoad` and `isConfirmDisabled` settle on the **same
render** the matching quote lands. Background refreshes of the same
amount keep `srcTokenAmount` unchanged, so the CTA stays enabled as
before.

## **Changelog**

CHANGELOG entry: Fixed the QuickBuy Buy button sometimes staying
disabled briefly after the quote finished loading.

## **Related issues**

Fixes: An issue where he QuickBuy Buy button sometimes staying disabled
briefly after the quote finished loading.

## **Manual testing steps**

```gherkin
Feature: QuickBuy Buy button enablement

  Scenario: Buy button enables as soon as the quote loads
    Given I open the QuickBuy bottom sheet for a token
    When I enter or select an amount and the quote loader spins
    Then the loader disappears when the quote completes
    And the Buy button becomes enabled on the same frame (no lag)

  Scenario: Buy button stays disabled while a new amount is being quoted
    Given a quote is already displayed for an amount
    When I change the amount so a new quote is fetched
    Then the Buy button is disabled until the quote for the new amount arrives
```

## **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
  - Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user

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

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

For performance guidelines and tooling, see the [Performance

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

## **Pre-merge reviewer checklist**

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

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Localized QuickBuy confirm/disable logic with added unit tests; no
auth, submission, or bridge API changes beyond when the button enables.
> 
> **Overview**
> Fixes QuickBuy **Buy** staying disabled briefly after the quote loader
finishes by replacing post-commit ref tracking of the “settled” amount
with a synchronous **`isActiveQuoteForCurrentAmount`** check.
> 
> **`isPendingQuoteRefresh`** now derives from whether the on-screen
quote matches the committed amount: atomic units from
**`calcTokenValue`** on the requested **`sourceTokenAmount`** are
compared to **`activeQuote.sentAmount`** (full wallet deduction), not
**`quote.srcTokenAmount`**, so gas-included/sponsored quotes still
enable the CTA when the displayed quote is valid.
> 
> Tests add default **`sentAmount`** on quote fixtures plus cases for
same-render loader/CTA sync and post-fee **`srcTokenAmount`** with
matching **`sentAmount`**.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
4124eb2. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

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

Co-authored-by: Xavier Brochard <xavier.brochard@consensys.net>
Co-authored-by: Cursor <cursoragent@cursor.com>
…y with and split Pay with/Receive flows (#31237)

- fix(quick-buy): show all held tokens in Pay with and split Pay
with/Receive flows (#31195)

## **Description**

In the QuickBuy bottom sheet, the **Pay with** picker only listed a
curated allowlist of native tokens and stablecoins. Tokens the user
actually held (e.g. CAKE, UP, dogwifhat) were missing, so they couldn't
pay with them.

This PR:

1. **Fixes the missing tokens bug.** `usePayWithTokens` now sources
every tradable token the user holds across the bridge-enabled source
chains (same `useTokensWithBalance` source the Bridge/Swap pickers use),
instead of a hardcoded candidate list.
2. **Cleanly splits the two flows.** The previously combined screen
branched internally on `tradeMode`. It is now split into
`QuickBuyPayWithScreen` (buy / "Pay with") and `QuickBuyReceiveScreen`
(sell / "Receive"), both rendering a shared presentational
`QuickBuyTokenSelectList`, routed by a small `QuickBuyTokenSelectScreen`
dispatcher.
3. **Extracts shared logic.** Token balance/fiat/exchange-rate
enrichment moved into a pure `enrichTokenBalance` helper reused by both
the "Pay with" and "Receive" hooks, plus a shared `tokenKey` util.
4. **Fixes fiat display for non-USD users.** QuickBuy is USD-first
(`currencyExchangeRate` is USD-per-token and the amount entry renders
`$`). The balance fiat was computed from `usdConversionRate` but
formatted with the user's selected currency, mislabeling a USD value as
e.g. `€2000.00`. Fiat fields are now formatted as USD to match the value
and the rest of the flow.

## **Changelog**

CHANGELOG entry: Fixed QuickBuy "Pay with" not showing all tokens the
user holds, and corrected the fiat amount currency shown for non-USD
users.

## **Related issues**

Fixes: [TSA-609](https://consensyssoftware.atlassian.net/browse/TSA-609)

## **Manual testing steps**

```gherkin
Feature: QuickBuy Pay with held tokens

  Scenario: user pays with an arbitrary held token
    Given I hold tokens that are not stablecoins or natives (e.g. CAKE, UP, dogwifhat)
    When I open the QuickBuy bottom sheet and tap "Pay with"
    Then I see all of my held, tradable tokens listed
    And I can select one and continue to the amount screen

  Scenario: user on a non-USD currency sees correct fiat
    Given my display currency is set to EUR
    When I open the "Pay with" picker
    Then each token's fiat value is shown in USD ($), matching the amount screen

  Scenario: user selling a position picks a stablecoin to receive
    Given I open QuickBuy in sell mode
    When I tap "Receive"
    Then I see the stablecoin options with the position chain offered first
```

## **Screenshots/Recordings**

### **Before**

<img width="333" height="699" alt="image"

src="https://github.com/user-attachments/assets/27e60e40-5121-46ef-b267-fc4abc8bb14f"
/>

### **After**

<img width="565" height="699" alt="image"

src="https://github.com/user-attachments/assets/d6583b51-7aa4-4079-9ad0-a96c0f490306"
/>

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding

Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling

guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

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

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

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

For performance guidelines and tooling, see the [Performance

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

## **Pre-merge reviewer checklist**

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

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

[TSA-609]:

https://consensyssoftware.atlassian.net/browse/TSA-609?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes which tokens can fund trades and how USD rates are computed
for amount entry; sell receive stables behavior is preserved but
enrichment rules (no stable $1 fallback on Pay with) differ from the old
hook.
> 
> **Overview**
> Fixes QuickBuy **Pay with** so users see **all held, tradable tokens**
(via Bridge’s `useTokensWithBalance`) instead of a hardcoded
native/stable allowlist, with strict pricing so only tokens with a
resolvable USD rate appear.
> 
> **Pay with** and **Receive** are split: buy uses
`QuickBuyPayWithScreen`, sell uses `QuickBuyReceiveScreen`, both backed
by shared `QuickBuyTokenSelectList` and routed by
`QuickBuyTokenSelectScreen` on the existing `payWith` screen.
> 
> Token balance/fiat/exchange-rate logic moves into pure
`enrichTokenBalance` (used by new `usePayWithTokens` and
`useReceiveTokens`); `sourceTokenCandidates` / `useSourceTokenOptions`
are removed. Fiat labels in the picker are formatted as **USD** to match
QuickBuy’s USD-first amount flow (fixes wrong currency symbol for
non-USD display settings).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f31322e. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

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

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

Co-authored-by: Xavier Brochard <xavier.brochard@consensys.net>
Co-authored-by: Cursor <cursoragent@cursor.com>
<!--
Please submit this PR as a draft initially.

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

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

  type=text           Section must contain non-placeholder prose.
  type=changelog      Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section blocks the PR
check.

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

## **Description**
sync stable into 7.81.0
<!-- mms-check: type=text required=true -->

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

## **Changelog**

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

<!--
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: N/A

## **Related issues**

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

Fixes: N/A

## **Manual testing steps**

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

## **Screenshots/Recordings**

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

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

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

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

## **Pre-merge author checklist**

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

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

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

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

#### Performance checks (if applicable)

- [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**
> Documentation-only CHANGELOG and release-link updates; no application
or runtime code changes.
> 
> **Overview**
> **Updates `CHANGELOG.md` for a stable-branch release sync** by
publishing a new **`[7.80.0]`** section and refreshing compare links at
the bottom of the file.
> 
> The **`7.80.0`** block documents shipped work under **Added** (e.g.
explore swap conversion tracking, explore search V2 metrics, batch sell
quotes setup, World Cup Predict tab), **Changed** (explore v2
simplification, Android 16KB page-size native dep patches, assets
controller bump, pure-black dark mode flag, Tron snap bump), and
**Fixed** (pure-black sheet surfaces, zero APY on money home, prediction
markets no longer accepting bets).
> 
> The **`[7.78.1]`** section is **expanded** beyond the existing
WebSocket `CloseEvent` crash fix to include a large set of **Added** and
**Fixed** bullets (Money Account, Card, Predict, Explore, Rewards,
swaps/bridge, onboarding, etc.) that are now grouped under that patch
version.
> 
> **Link footer:** `[Unreleased]` now points at `v7.80.0...HEAD`, and a
new **`[7.80.0]`** compare URL (`v7.78.0...v7.80.0`) is added.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
d6e1e8f. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ick buy when only viewed token held (#31403)

- fix(token-details): cp-7.81.0 show swap/quick buy when only viewed
token held (#31393)

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

On the Token Details screen, the Swap button and the QuickBuy
(lightning/flash) icon were both gated on `selectHasEligibleSwapSource`,
which the footer called with the currently-viewed token **excluded**. As
a result, **a user whose only funded asset was the token they were
viewing (e.g. holding only ETH, on the ETH page) saw neither control,
and only the fiat Buy fallback was shown**.

This is incorrect: the swap handler (`useHandleOnSwap`) already swaps
the held token *away* when the user holds it, and QuickBuy's sell mode
operates on the position token. So holding only the viewed token is a
perfectly valid reason to surface Swap and QuickBuy.

The fix calls the selector with no exclusion args in
`useStickyTokenActions`, so the viewed token counts as a
fundable/swappable asset. The selector's optional `excludedChainId` /
`excludedAddress` parameters are intentionally retained for any future
caller that genuinely needs "any funded asset except X".

Behavioral delta: for a held token that is not fiat-buyable and with no
other holdings, the Buy on-ramp fallback no longer shows; Swap is shown
instead. For buyable tokens (e.g. ETH) both still show.

## **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: Fixed the Swap and Quick Buy buttons not appearing on
the token details screen when the only funded asset was the token being
viewed.

## **Related issues**

Fixes: Issue where the Swap button wouldn't show, preventing me from
swapping a token I actually hold.

## **Manual testing steps**

```gherkin
Feature: Token details trade actions for a single-asset wallet

  Scenario: User holding only the viewed token sees Swap and Quick Buy
    Given my wallet holds a positive balance of only one token (e.g. ETH)
    And I have no other funded assets
    When I open the Token Details screen for that token
    Then the Swap button is visible
    And the Quick Buy (lightning) icon is visible
    And tapping Quick Buy opens the QuickBuy sheet where I can sell the token
```

## **Screenshots/Recordings**

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

### **Before**

<img width="1440" height="805" alt="image"

src="https://github.com/user-attachments/assets/4e58144c-218a-473c-ad91-88c06c01499a"
/>

### **After**

<img width="694" height="919" alt="image"

src="https://github.com/user-attachments/assets/b095e246-7584-41c1-a19f-01492669cd16"
/>

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Localized change to swap-eligibility gating and footer visibility on
Token Details; no auth, payments, or data-layer changes.
> 
> **Overview**
> Fixes Token Details **Swap** and **Quick Buy** staying hidden when the
user’s only funded asset is the token on screen.
> 
> `useStickyTokenActions` no longer passes the viewed token into
`selectHasEligibleSwapSource` as an exclusion.
**`selectHasEligibleSwapSource`** is simplified to a state-only check:
any asset with positive fiat balance counts, including the current
token, since that balance is a valid swap source.
> 
> Tests now assert the hook uses the selector without exclusions and
that a single funded “viewed” token yields eligibility **true**. For
wallets with only one non–fiat-buyable holding, the footer may show
**Swap** instead of the Buy on-ramp fallback when swap eligibility is
true.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
5722fd1. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

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

Co-authored-by: Xavier Brochard <xavier.brochard@consensys.net>
Co-authored-by: Cursor <cursoragent@cursor.com>
This PR updates the change log for 7.81.0. (Hotfix - no test plan
generated.)

---------

Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
Co-authored-by: tommasini <tommasini15@gmail.com>
Co-authored-by: tommasini <46944231+tommasini@users.noreply.github.com>
runway-github Bot and others added 17 commits June 11, 2026 09:13
…ial carousel Rive animations cp-7.81.0 (#31557)

- fix(perps): prevent Android crash in tutorial carousel Rive animations
cp-7.81.0 (#31547)

## **Description**

The Perps "Learn the basics" tutorial carousel crashes on Android when
navigating through the screens.

**Root cause:** `ScrollableTabView` renders all child tabs
simultaneously, which means 4–5 `<Rive>` components (one per tutorial
screen with an animation) are all mounted with `autoplay={true}` at the
same time. On Android, the Rive native renderer cannot handle multiple
concurrent GPU-accelerated animation instances and crashes.

**Fix:** Only mount the `<Rive>` component for the currently visible tab
(`currentTab === index`). This ensures a single native Rive renderer
instance exists at any time. When the user swipes or taps Continue, the
previous instance is unmounted and the next one takes its place.

iOS is unaffected because its Metal rendering pipeline handles
concurrent Rive instances more gracefully.

## **Changelog**

CHANGELOG entry: Fixed a crash on Android when navigating through the
Perps tutorial carousel

## **Related issues**

Fixes: #31540

## **Manual testing steps**

```gherkin
Feature: Perps tutorial carousel stability on Android

  Scenario: user completes the full tutorial without crash
    Given the user has not completed the Perps tutorial
    When user taps Perps and goes through "Learn the Basics of Perps"
    Then the app does not crash
    And all tutorial screens display their Rive animations correctly

  Scenario: user re-enters tutorial from Perps home
    Given the user is on the Perps home screen
    When user scrolls down and taps "Learn the Basics of Perps"
    And user taps Continue through all screens
    Then the app does not crash
    And the user reaches the final screen successfully
```

## **Screenshots/Recordings**

N/A — no visual change; this is a crash fix. The tutorial screens render
identically, only one Rive animation is mounted at a time instead of all
simultaneously.

### **Before**

App crashes on Android when navigating through tutorial carousel
screens.

### **After**

Tutorial carousel completes without crash on Android.

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Single conditional around Rive mounting in the tutorial carousel;
behavior is unchanged except avoiding concurrent animations on Android.
> 
> **Overview**
> Fixes an **Android crash** in the Perps “Learn the basics” tutorial by
ensuring only one native **Rive** animation is mounted at a time.
> 
> `ScrollableTabView` keeps every tab’s children in the tree, so every
screen with `riveArtboardName` used to mount `<Rive autoplay>` together.
The change adds `index` in the screen map and renders the animation only
when **`currentTab === index`**, so swiping or tapping Continue unmounts
the previous instance before the next one loads. No intended UI change
on iOS.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
17b73bc. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[fe7877a](fe7877a)

Co-authored-by: Michal Szorad <michal.szorad@consensys.net>
… and related components (7.81.0) (#31568)

## Summary
Cherry-pick of one merged PR from `main` into `release/7.81.0`: 

- #31465 - feat: update
World Cup event count in PredictionsSection and related components

## Related
- Cherry-pick of b54fda6 from main

CHANGELOG entry: null

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Read-only homepage UI and a lightweight Polymarket fetch; no auth or
payment paths. Main risk is wrong/missing subtitle if the pagination API
fails.
> 
> **Overview**
> The homepage Predict World Cup discovery row now shows **total event
count from Polymarket’s `/events/pagination` API** (via new
`useHomepagePredictWorldCupEventCount`) instead of inferring it from how
many markets were loaded and `hasMore`.
> 
> `PredictionsSection` loads and refetches that count with the World
Cup/NBA discovery feeds, includes it in loading state, and passes
`worldCupEventCount` into the discovery UI.
**`HomepagePredictWorldCupDiscovery`** always uses the overflow copy
(e.g. `48+ events in total`) when a numeric total exists, and
**`MensWorldCupRow`** hides the subtitle until the count is available.
Tests and React Query mocks were updated for the new hook and label
behavior.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
b54fda6. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
)

- chore: bump `network-controller` and `controller-utils` cp-7.81.0
(#31128)

<!--
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?
-->
Bumping `@metamask/network-controller` to `^32.0.0` and
`@metamask/controller-utils` to `^12.1.0`:

```markdown
## [32.0.0]

### Changed

- **BREAKING:** Remove Sei, MegaETH, Avalanche, and ZKSync from list of default networks ([#8767](MetaMask/core#8767))
  - You will need to add them as network configurations first before switching to them.
- Bump `@metamask/controller-utils` from `^12.0.0` to `^12.1.0` ([#8774](MetaMask/core#8774))
```

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

## **Related issues**

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

Closes: https://consensyssoftware.atlassian.net/browse/WPN-1239

## **Manual testing steps**

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


- Onboard as new user on a fresh install
- Observe that zkSync, Avalanche, and MegaETH are not enabled by default

## **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
<!-- [screenshots/recordings] -->

### **After**

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

## **Pre-merge author checklist**

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

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

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

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding

Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling

guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

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

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

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

For performance guidelines and tooling, see the [Performance

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

## **Pre-merge reviewer checklist**

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

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> The breaking default-network removal can affect users or flows that
relied on Avalanche, ZKSync, MegaETH, or Sei being preconfigured;
otherwise this is primarily a dependency and test-fixture alignment
change.
> 
> **Overview**
> Bumps **`@metamask/network-controller`** to **32.0.0** and
**`@metamask/controller-utils`** to **12.1.0** (including `package.json`
resolutions and `yarn.lock`).
> 
> That **breaking** network-controller release drops **Sei, MegaETH,
Avalanche, and ZKSync** from built-in default EVM networks, so fresh
installs no longer ship those chain configs unless users add them
manually.
> 
> Test fixtures are aligned: **`initial-background-state.json`** no
longer seeds MegaETH, ZKSync, or Avalanche mainnet entries, and
**`AddressSelector.test.tsx`** updates the expected EVM-only network
list to match.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
a8aa9b6. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[6d27922](6d27922)

Co-authored-by: Michele Esposito <34438276+mikesposito@users.noreply.github.com>
)

- fix(predict): keep time-slot scroll anchored left when live slot
expires cp-7.81.0 (#31231)

## **Description**

This PR bundles four UI/behavior fixes on the Predict **crypto up/down**
details screen (plus one shared positions tweak). All changes are
confined to `app/components/UI/Predict/`.

**1. Time-slot picker loses its left anchor when the live slot expires
(primary fix)**
When the live time slot expired and rolled to the next window, the
horizontal `TimeSlotPicker` no longer kept the live/selected pill
anchored at the left. Root cause: the auto-scroll read pill
x-coordinates from a cached `pillPositions` map that (1) retained stale
entries for markets that had been filtered out, and (2) was read by a
fixed 50ms settle timer that raced ahead of React Native's async
re-layout — so `scrollTo` used the pre-shift offset and over-scrolled.
- Prune `pillPositions` to only currently-rendered markets whenever
`markets` changes.
- Re-run the settle-delay anchor on the ordered `marketsKey` so a left
shift re-anchors even when the resolved selection is unchanged.
- Re-anchor immediately when the selected pill reports a new layout `x`,
beating the timer/layout race.
- Adds a regression test that reproduces the expiry race (verified
failing pre-fix, passing post-fix).

**2. Even spacing around the time-slot picker**
The picker is a flush `h-11` container with no vertical padding of its
own, so the gap above (title `pb-3` = 12px) and below (price summary
`pt-5` = 20px) were uneven. Changed the price-summary top padding `pt-5
→ pt-3` so the picker has equal 12px above and below.

**3. Centered separator dot in positions rows**
The `Up/Down · entry` separator dot was baseline-glued to the entry
label via a `' · '` string, so it sat slightly off-center. Split it into
its own `Text` node so it aligns optically in the center-aligned row.

**4. Remove the `$100 → $X` payout preview from the up/down CTA + grow
the chart**
Removed the payout estimate under the buy buttons on the crypto up/down
details page by no longer passing `showPayoutEstimate` to the shared
`PredictMarketDetailsActions`. The prop, formatter, and gated rendering
remain intact on that component for any other surface that wants the
preview (none currently enable it), so the change is regression-safe.
The freed vertical space is reclaimed by growing the with-positions
chart height (ratio `0.4 → 0.44`, max `380 → 430`) so the chart fills
the gap above the sticky actions while keeping the first position row
visible and the rest scrollable.

## **Changelog**

CHANGELOG entry: Fixed the Predict crypto up/down time-slot selector so
the live slot stays anchored to the left when it rolls to the next
window, evened out the spacing around the selector, and removed the
payout estimate from the buy buttons to give the price chart more room.

## **Related issues**

Refs: No external ticket — incremental UX polish on the Predict crypto
up/down details screen reported during QA review (live-slot scroll
anchoring regression, uneven selector spacing, off-center separator dot,
payout-preview removal + chart sizing).

## **Manual testing steps**

```gherkin
Feature: Predict crypto up/down details screen

  Scenario: Live time slot stays anchored left when it expires
    Given I am on a crypto up/down market details screen
    And the live time slot is the left-most pill in the selector
    When the live slot expires and the next slot becomes live
    Then the new live slot is anchored to the left edge of the selector
    And the selector is not over-scrolled or visually shifted

  Scenario: Time-slot selector is evenly spaced
    Given I am on a crypto up/down market details screen
    Then the vertical space above and below the time-slot selector is equal

  Scenario: Separator dot is centered in a position row
    Given I am on a crypto up/down market details screen
    And I hold at least one position in the series
    Then the dot between the outcome label and the entry price is vertically centered

  Scenario: No payout preview under the buy buttons and chart fills the space
    Given I am on a crypto up/down market details screen
    Then no "$100 -> $..." payout estimate is shown under the Up and Down buttons
    And the price chart uses the freed space above the sticky action buttons

  Scenario: First position visible and the rest scroll
    Given I am on a crypto up/down market details screen
    And I hold more positions than fit on screen
    Then the first position row is visible above the sticky action buttons
    And the remaining position rows are reachable by scrolling
```

## **Screenshots/Recordings**

### **Before**

N/A — author to attach device capture before marking Ready for review
(changes are visual layout tweaks on the crypto up/down details screen
that need a simulator/device to record).

### **After**

N/A — author to attach device capture before marking Ready for review.

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Predict UI-only changes in TimeSlotPicker and crypto up/down details;
scroll logic is covered by new tests with no auth or data-path impact.
> 
> **Overview**
> Fixes **Predict crypto up/down** layout and **TimeSlotPicker** scroll
behavior when a live slot rolls off.
> 
> **Time slot picker:** When the live pill disappears and the list
shifts left, horizontal scroll no longer drifts off the left edge. Stale
`pillPositions` entries are pruned, anchoring re-runs on `marketsKey`
changes, and the selected pill’s `onLayout` re-scrolls immediately so a
50ms timer doesn’t win a race against re-layout. Regression tests cover
initial anchor and post-expiry re-anchor.
> 
> **Details screen polish:** Price-summary top padding is tightened
(`pt-5` → `pt-3`) so spacing above/below the picker matches. With
positions, the chart grows (ratio **0.44**, max **430px**) after
dropping the buy-button payout estimate (`showPayoutEstimate` no longer
passed). **Position rows:** the `·` separator is its own `Text` node for
better vertical alignment with the outcome/entry labels.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
8308aa7. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[a41a3ca](a41a3ca)

Co-authored-by: hunty <hunter.goodreau@consensys.net>
…nt count in English localization cp-7.81.0 (#31582)

- fix(locales): update overflow text for event count in English
localization cp-7.81.0 (#31566)

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

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

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

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

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

## **Description**

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

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
Updates the World Cup homepage discovery overflow copy from “events in
total” to “markets in total”.
This matches the product language for the overflowing World Cup market
count while leaving the normal non-overflow event count unchanged.


## **Changelog**

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

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

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

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

CHANGELOG entry: Updated World Cup discovery copy to say markets instead
of events for overflowing counts.

## **Related issues**

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

Fixes:

## **Manual testing steps**

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

```gherkin
Feature: World Cup discovery card copy
  Scenario: user sees overflowing World Cup market count
    Given the Predictions homepage discovery card has more World Cup items than the display limit
    When the user views the World Cup discovery row
    Then the overflow count says "{{count}}+ markets in total"
```

## **Screenshots/Recordings**

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

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

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

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

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding

Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling

guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

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

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

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

For performance guidelines and tooling, see the [Performance

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

## **Pre-merge reviewer checklist**

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

- [ ] 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-only English localization and test assertion change with no logic
or data-handling impact.
> 
> **Overview**
> Updates World Cup homepage discovery **overflow** copy from “events”
to **markets** so overflowing counts match product terminology.
> 
> The English string
`predict.homepage_discovery.events_in_total_overflow` now renders
`{{count}}+ markets in total` instead of `{{count}}+ events in total`.
The non-overflow key `events_in_total` is unchanged. The
`PredictionsSection` test expectation for the discovery row was aligned
with the new copy.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f19f028. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[c101846](c101846)

Co-authored-by: Patryk Łucka <5708018+PatrykLucka@users.noreply.github.com>
)

- fix(locales): update overflow text for event count in English
localization cp-7.81.0 (#31566)

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

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

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

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

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

## **Description**

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

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
Updates the World Cup homepage discovery overflow copy from “events in
total” to “markets in total”.
This matches the product language for the overflowing World Cup market
count while leaving the normal non-overflow event count unchanged.


## **Changelog**

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

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

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

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

CHANGELOG entry: Updated World Cup discovery copy to say markets instead
of events for overflowing counts.

## **Related issues**

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

Fixes:

## **Manual testing steps**

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

```gherkin
Feature: World Cup discovery card copy
  Scenario: user sees overflowing World Cup market count
    Given the Predictions homepage discovery card has more World Cup items than the display limit
    When the user views the World Cup discovery row
    Then the overflow count says "{{count}}+ markets in total"
```

## **Screenshots/Recordings**

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

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

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

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

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding

Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling

guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

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

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

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

For performance guidelines and tooling, see the [Performance

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

## **Pre-merge reviewer checklist**

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

- [ ] 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-only English localization and test assertion change with no logic
or data-handling impact.
> 
> **Overview**
> Updates World Cup homepage discovery **overflow** copy from “events”
to **markets** so overflowing counts match product terminology.
> 
> The English string
`predict.homepage_discovery.events_in_total_overflow` now renders
`{{count}}+ markets in total` instead of `{{count}}+ events in total`.
The non-overflow key `events_in_total` is unchanged. The
`PredictionsSection` test expectation for the discovery row was aligned
with the new copy.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f19f028. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[c101846](c101846)

Co-authored-by: Patryk Łucka <5708018+PatrykLucka@users.noreply.github.com>
…Action (#31588)

- chore: New Crowdin Translations by GitHub Action cp-7.81.0 (#30563)

Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
Co-authored-by: Laurel <153323700+i18nlaurel@users.noreply.github.com> [60627b1](60627b1)
…anvas override on Android to prevent Earn onboarding crash (#31586)

- fix: remove RiveRenderer.defaultRenderer Canvas override on Android to
prevent Earn onboarding crash (#31475)

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

Removed the global `RiveRenderer.defaultRenderer(...,
RiveRendererAndroid.Canvas)` call in `FoxLoader` during app init.
Although this lived in the splash-screen loader, `defaultRenderer` is a
process-wide setting that forced every Rive view in the app onto
Android's Canvas renderer `Surface.lockCanvas path`. This caused the
Money/Earn onboarding stepper to hard-crash `SIGABRT`/`SIGSEGV` on
Android when the Rive view tore down during tab navigation, the worker
thread called `lockCanvas` on an already-released Surface, leaving a
pending JNI exception that ART aborted on. Tombstone confirmed on Pixel
6a / Android 16. Reverting to the default Rive GPU renderer removes the
`lockCanvas` code path entirely.

iOS is unaffected (already uses the GPU renderer).

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

## **Changelog**

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

<!--
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 an Android crash when entering Earn onboarding
caused by the Rive Canvas renderer being forced app-wide.

## **Related issues**

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

Fixes: #31166
#31167

## **Manual testing steps**

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

```gherkin
Feature: Earn onboarding no longer crashes on Android

  Scenario: User enters Earn onboarding on Android after fresh install
    Given the app is built in release mode on a Pixel 6a (or equivalent) running Android 16
    And the user has completed initial app load (FoxLoader splash animation plays)

    When the user taps the Money/Earn tab
    And the Rive onboarding stepper mounts
    Then the app does not crash
    And the onboarding animation renders and steps through normally

  Scenario: Splash animation still plays on Android
    Given a fresh launch on Android
    When the FoxLoader splash screen appears
    Then the fox Rive animation plays to completion without visual regressions
```

## **Screenshots/Recordings**

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



https://github.com/user-attachments/assets/32c75ebd-8a93-4afb-ae8b-250fe4540b4f

### **Before**

### Crash on open



https://github.com/user-attachments/assets/75339490-e41f-4c42-9853-c6bce7baaffc

### Crash on close



https://github.com/user-attachments/assets/8fe061e9-6e5d-4c21-8d46-06082783de90

### **After**



https://github.com/user-attachments/assets/32c75ebd-8a93-4afb-ae8b-250fe4540b4f

## **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]
> **Medium Risk**
> Small splash-only change with process-wide rendering impact on
Android; fixes a production crash but may reintroduce any original
Canvas-renderer motivation (e.g. splash geometry).
> 
> **Overview**
> Removes the **Android-only** `RiveRenderer.defaultRenderer(...,
RiveRendererAndroid.Canvas)` setup from `FoxLoader` so Rive is no longer
forced app-wide onto the Canvas renderer during splash init.
> 
> That global override affected every Rive view (not just the fox
splash), which led to **SIGABRT/SIGSEGV** when Earn/Money onboarding
Rive UI tore down during tab navigation (`lockCanvas` on a released
Surface). **iOS is unchanged**; Android again uses Rive’s default GPU
renderer.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
a212356. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
[7929023](7929023)

Co-authored-by: Vince Howard <vincenguyenhoward@gmail.com>
# 🚀 v7.81.0 Testing & Release Quality Process

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

---

## 📋 Key Processes

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

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

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

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

---

## 🗓️ Timeline and Milestones

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

---

## ✅ Signoff Checklist

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

# Team sign-off checklist
- [x] Accounts
- [x] Assets
- [x] Bots Team
- [x] Card
- [x] Confirmations
- [x] Core Platform
- [x] Design System
- [x] Earn
- [x] Engagement
- [x] MetaMask Product Operations
- [x] Mobile Platform
- [x] Mobile UX
- [x] Money Movement
- [x] Networks
- [x] Onboarding
- [x] Perps
- [x] Predict
- [x] Rewards
- [x] Social & AI
- [x] Swaps and Bridge
- [x] team-release
- [x] Transactions
- [x] Wallet Integrations

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

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

Many thanks in advance

# Reference
- Testing plan sheet -
https://docs.google.com/spreadsheets/d/1tsoodlAlyvEUpkkcNcbZ4PM9HuC9cEM80RZeoVv5OCQ/edit?gid=404070372#gid=404070372
@metamaskbotv2 metamaskbotv2 Bot requested review from a team as code owners June 12, 2026 21:42
@github-actions

Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@matthewwalsh0 matthewwalsh0 requested a review from vinistevam June 13, 2026 11:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants