release: 8.5.0 - #33734
Conversation
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
<!-- mms-check: type=text required=true -->
Adds watchlist filtering to the **Explore → Trending Tokens**
full-screen view
([ASSETS-3124](https://consensyssoftware.atlassian.net/browse/ASSETS-3124)).
**Why:** Users need a way to view only their watchlisted tokens from
Explore Trending, consistent with the homepage watchlist experience.
**What changed:**
- **Watchlist star filter pill** in `FilterBar` (before Price change /
All networks / 24h), gated by `assetsGlobalWatchlistV1`
(`selectTokenWatchlistEnabled`)
- **Toggle behavior:** tapping the star switches the list from trending
search (`useTrendingSearch`) to the user's watchlist
(`useTokenWatchlistQuery` + `mapWatchlistTokenToTrendingAsset`)
- **Empty state:** when the watchlist filter is active and there are no
items, shows the shared `WatchlistEmptyState` illustration/copy
- **Analytics:** adds `TokenDetailsSource.ExploreWatchlistFilter` and
passes it through list rows when the watchlist filter is active
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: Added a watchlist filter to the Trending Tokens explore
screen so users can view only their watchlisted tokens.
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Fixes:
[ASSETS-3124](https://consensyssoftware.atlassian.net/browse/ASSETS-3124)
Figma:
https://www.figma.com/design/FDAyhLhfujFntyZhnvoIRC/Watchlist?node-id=4032-32555&m=dev
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
## **Manual testing steps**
```gherkin
Feature: Trending Tokens watchlist filter
Scenario: Watchlist filter hidden when feature flag is off
Given assetsGlobalWatchlistV1 is disabled
When the user opens Explore → Trending Tokens
Then the star filter pill is not shown
And the list shows trending tokens as before
Scenario: User toggles watchlist filter with watchlisted tokens
Given assetsGlobalWatchlistV1 is enabled
And the user has one or more tokens on their watchlist
When the user opens Explore → Trending Tokens
And taps the star filter pill
Then the pill appears selected
And the list shows only watchlisted tokens
When the user taps the star filter pill again
Then the pill is unselected
And the list returns to trending tokens
Scenario: Empty watchlist with filter active
Given assetsGlobalWatchlistV1 is enabled
And the user has no watchlisted tokens
When the user opens Explore → Trending Tokens
And taps the star filter pill
Then the watchlist empty state is shown (icon, title, subtitle)
Scenario: Pull-to-refresh in watchlist mode
Given the watchlist filter is active
When the user pulls to refresh
Then watchlist data is refetched (not trending search)
Scenario: Token Details analytics source
Given the watchlist filter is active
And the list shows at least one token
When the user taps a token row
Then Token Details opens with source explore_watchlist_filter
```
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
https://github.com/user-attachments/assets/a00844bf-7dc8-42a3-bc8f-44b1ca4f554c
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
[ASSETS-3124]:
https://consensyssoftware.atlassian.net/browse/ASSETS-3124?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> User-facing Explore UI and analytics attribution only, behind an
existing feature flag, with broad unit test coverage and no auth or
payment changes.
>
> **Overview**
> Adds a **watchlist star filter** to Explore → Trending Tokens when
`selectTokenWatchlistEnabled` is on. Toggling it switches the list from
trending search to the user’s watchlist (mapped to `TrendingAsset`),
applies existing network and price-change filters, shows shared
`WatchlistEmptyState` when the watchlist is empty, and refetches
watchlist data on pull-to-refresh instead of trending pagination.
>
> Introduces `TokenDetailsSource.ExploreWatchlistFilter`, treats it as
an Explore source for analytics, and threads `tokenDetailsSource`
through `FilterBar`, `TokenListPageLayout`, and `TrendingTokensList` to
row navigation. The price-change filter stays enabled when watchlist
rows are shown even if trending search is empty.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
4730cfb. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…nParams (phase 3) (#33227) <!-- 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? --> - **Money:** introduce `MoneyScreensStackParamList`, `MoneyModalsNavigationParamList`, and `MoneyConfirmationsNavigationParamList`; type `MoneyScreens` / `MoneyModals` / `MoneyConfirmations` with `NavigatorScreenParams`; wire the three Money navigators. - **Ramp:** introduce `RampScreensStackParamList`, `RampModalsNavigationParamList`, and `RampTokenListRootParamList`; type `RampModals`, `RampTokenSelectionRoot`, `RampTokenSelection`, and `RampHeadlessEntry` with `NavigatorScreenParams`; wire V2 `routes.tsx` and Aggregator `RampModals`. - Keep feature-level `MoneyNavigationParamList` / `RampNavigationParamList` for flat screens + nested entry points. - `RampModalsNavigationParamList` includes both V2 and Aggregator modal screens because both stacks share the `RampModals` route name. Phase 3 of the navigation typing migration for Money + Ramp, following Perps/Predict. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry:null ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes:https://consensyssoftware.atlassian.net/browse/MCWP-674 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> n/a ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> n/a ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [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** > Type-only navigation refactor with no intended runtime changes; risk is limited to compile-time breakage or mismatched nested `{ screen, params }` typings. > > **Overview** > Continues the navigation typing migration for **Money** and **Ramp** by splitting monolithic param lists into per-stack types and wiring them through `createNativeStackNavigator<…>()` and `NavigatorScreenParams` on the root stack. > > **Money:** Adds `MoneyScreensStackParamList`, `MoneyModalsNavigationParamList`, and `MoneyConfirmationsNavigationParamList` (including `ConfirmationParams` on redesigned confirmations). Renames the three in-feature stacks to `TabStack`, `ConfirmationStack`, and `ModalStack` with generics. `MoneyNavigationParamList` is now an intersection of those stacks plus flat routes and typed `MoneyScreens` / `MoneyModals` / `MoneyConfirmations` entry points. `RootStackParamList` replaces `NestedNavigationParams` on those three routes. > > **Ramp:** Adds `RampScreensStackParamList`, `RampModalsNavigationParamList` (V2 + Aggregator modals under shared `RampModals`), `RampTokenListRootParamList`, `RampAggregatorScreensStackParamList`, and `RampAggregatorRootParamList`. V2 `routes.tsx` and Aggregator `routes/index.tsx` use typed `RootStack` / `ScreensStack` / `ModalsStack`. Root typing updates `RampModals`, `RampTokenSelection` / `RampHeadlessEntry` (token-list root), and `RampTokenSelectionRoot` (inner V2 screen stack); several Ramp modal routes on the root list now alias `RampModalsNavigationParamList` keys. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 0a0af0b. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
<!-- mms-check: type=text required=true -->
hook `useActivityBlockExplorer` is return a incorrect explorer url for
non-evm, it assume every non-evm is using `${baseURl}/tx/${hash}`
pattern
the fix using the predefine function getTransactionUrl from multichain
urls, which already done in a better sharp
@vinnyhoward
This useActivityBlockExplorer somehow is redundant from
`useMultichainBlockExplorerTxUrl`, but the PR is not going to make
change to replace `useActivityBlockExplorer`, but we should consider to
consolidate it
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: Fixed useActivityBlockExplorer return incorrect URL for
non-evm
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Fixes:
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **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
- [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
- [ ] 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**
> Scoped change to activity explorer link resolution with existing
multichain URL helpers; EVM path unchanged and tests cover the new
behavior.
>
> **Overview**
> **Activity details** non-EVM “view on explorer” links were built with
a one-size-fits-all `${baseUrl}/tx/${hash}` (or simple template) rule,
which produced wrong URLs for chains like Solana and Tron.
>
> Non-EVM resolution now delegates to multichain
**`getTransactionUrl`**, which uses the existing per-chain explorer URL
formats. EVM behavior is unchanged: it still resolves the base URL from
network configuration and **`getBlockExplorerTxUrl`**. Unsupported
non-EVM chain IDs return no link when **`getTransactionUrl`** yields an
empty URL.
>
> Tests were aligned to assert Solana and Tron mainnet URLs and to
expect **`undefined`** for unknown non-EVM chains instead of the old
generic templating cases.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
51676dc. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description** Upgrades design system packages to align with the [v54.0.0 release](https://github.com/MetaMask/metamask-design-system/releases/tag/v54.0.0). **Packages upgraded:** - `@metamask/design-system-react-native`: `^0.35.0` → `^0.36.0` - `@metamask/design-system-twrnc-preset`: `^0.7.0` → `^0.8.0` - `@metamask/design-system-shared` (transitive): `^0.29.0` → `^0.30.0` **Breaking changes addressed:** - **`Slider`:** Renamed `onTick` → `onMark` for haptic feedback when crossing mark thresholds. Updated Batch Sell Review token row consumer and tests; extended the twrnc-preset Jest mock with `useTheme` / `usePureBlack` / `getThemeColors` for themed Slider marks. ### Other breaking changes (no code changes needed) - **`Content` / `ListItem`:** `verticalAlignment` / `ContentVerticalAlignment` / `ListItemVerticalAlignment` replaced by `variant` / `ContentVariant` / `ListItemVariant` (`OneLine`, `TwoLines`, `MultiLine`; default `TwoLines`). No Mobile call sites used the removed API. Activity list MMDS `ListItem` continues to work on the default `TwoLines` variant. - **`Slider` mark config:** Legacy `rangeLabelSteps` / `formatStepLabel` / `stepToValue` / `tickThresholds` consolidated into a single `marks` prop. Batch Sell only uses `showRangeDots` / haptics and relies on `DEFAULT_MARKS`. **New additions available for future use:** - `BannerBase` / `BannerAlert` `actionButtonLayout` (`Below` default, `End` for beside-body placement) - `SliderMarkColor` / unified `marks` API for themed Slider mark colors - `getThemeColors` export from `@metamask/design-system-twrnc-preset` **Upstream fixes included in this release:** - `Slider`: Fixed drag jerking when the controlled `value` updates mid-gesture **Legacy component deprecations:** - No new deprecations added — all matching legacy components in `app/component-library/` already have `@deprecated` JSDoc notices from prior upgrades ## **Changelog** CHANGELOG entry: Upgrades design system libraries to v54.0.0 and migrates Batch Sell Slider `onTick` to `onMark` ## **Related issues** Fixes: N/A ## **Manual testing steps** Feature: Design system upgrade to v54.0.0 Scenario: Core app functionality is unaffected Given I am on the main app screen When I navigate through the primary user flows Then the UI renders correctly with no visual regressions Scenario: Activity list rows using MMDS ListItem still render correctly Given I open the Activity list When I view rows with title and subtitle Then row layout and spacing look correct (default TwoLines variant; local minHeight overrides still apply) Scenario: Batch Sell Slider still works after onMark migration Given Batch Sell is enabled (`MM_BATCH_SELL_ENABLED=true` and remote flag / `OVERRIDE_REMOTE_FEATURE_FLAGS`) When I open Trade → Batch Sell, select tokens, and reach Batch Sell Review Then each token row Slider responds to drag/tap, grip haptics fire, and mark-crossing haptics still fire ## **Screenshots/Recordings** ### **Before** ### **After** Activity List https://github.com/user-attachments/assets/4e329d57-a3e9-4c0f-bd53-14ee2616d45b Batch Sell Slider https://github.com/user-attachments/assets/e66edef9-d4df-47f5-a66f-2d316da5e8fd ## **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. Co-authored-by: Cursor <cursoragent@cursor.com>
## Version Bump After Release This PR bumps the main branch version from 8.4.0 to 8.5.0 after cutting the release branch. ### Why this is needed: - **Nightly builds**: Each nightly build needs to be one minor version ahead of the current release candidate - **Version conflicts**: Prevents conflicts between nightlies and release candidates - **Platform alignment**: Maintains version alignment between MetaMask mobile and extension - **Update systems**: Ensures nightlies are accepted by app stores and browser update systems ### What changed: - Version bumped from `8.4.0` to `8.5.0` - Platform: `mobile` - Files updated by `set-semvar-version.sh` script ### Next steps: This PR should be **manually reviewed and merged by the release manager** to maintain proper version flow. ### Related: - Release version: 8.4.0 - Release branch: release/8.4.0 - Platform: mobile - Test mode: false --- *This PR was automatically created by the `create-platform-release-pr.sh` script.* Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
…3) (#33306) <!-- 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? --> **Phase 3 of the incremental React Navigation typing migration — app shell navigators.** Shared navigation hosts (`AssetStackFlow`, `WalletTabHome`, `SettingsView`, `TrendingView`, `BrowserTabHome`, `Webview`, `SetPasswordFlow`, `ImportPrivateKeyView`, `RootModalFlow`, `Home`, `Main`) were still loosely typed as `NestedNavigationParams` (or equivalent `{ screen: string; params?: object }`), so nested `navigate(container, { screen, params })` calls into those shells could not be checked against real screen param shapes. This PR adds shell-level param lists and wires them into `RootStackParamList` via `NavigatorScreenParams`, matching the Phase 3 pattern already used for feature stacks (Perps / Rewards / Predict / Card / Earn / etc.). This is primarily **types-only** — no intentional navigation architecture change. One small Onboarding call-site cleanup aligns SuccessErrorSheet params with the typed sheet contract (`primaryButtonLabel`). ### What changed **Shell param lists (`app/components/Nav/Main/types/navigation.ts`)** - Shells 1: `AssetStackParamList`, `WalletTabStackParamList` / `WalletTabHomeParamList`, `SettingsStackParamList` - Shells 2: `TrendingViewStackParamList`, `BrowserTabHomeParamList`, `WebviewStackParamList`, `SetPasswordFlowParamList`, `ImportPrivateKeyStackParamList` - Shells 3: `MoneyTabStackParamList`, `TransactionsHomeParamList`, `RewardsHomeParamList`, `HomeTabsParamList`, `MainStackParamList`, `MainFlowParamList` **Root modal flow (`app/core/NavigationService/types.ts`)** - `RootModalFlowParamList` — screens registered inside App’s `RootModalFlow` - `RootModalFlow` / `Home` / `Main` (and the Shells 1–2 hosts above) → `NavigatorScreenParams<…>` **Param accuracy / call-site cleanup** - Tightened stub shapes for `TransactionDetailsSheetParams` and `MultichainTransactionDetailsParams` to match what those sheets actually receive - Onboarding SuccessErrorSheet navigations now pass `primaryButtonLabel` (was incorrect `buttonLabel`) ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry:null ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes:https://consensyssoftware.atlassian.net/browse/MCWP-674 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> N/A ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [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** > Compile-time navigation typing and param-shape fixes; the only runtime tweak is correcting SuccessErrorSheet button props on onboarding error flows. > > **Overview** > **Phase 3** of the React Navigation typing migration: app-shell navigators that were still `NestedNavigationParams` (or loose `{ screen, params }`) now have dedicated param lists and are wired into `RootStackParamList` via `NavigatorScreenParams`. > > A new `navigation.ts` defines shell lists for asset/wallet/settings stacks, home tabs, main flow, browser/webview/set-password/import flows, and related hosts. `NavigationService/types.ts` adds **`RootModalFlowParamList`** and replaces loose typing on **`Main`**, **`Home`**, **`RootModalFlow`**, **`SettingsView`**, **`WalletTabHome`**, **`AssetStackFlow`**, and similar routes with nested `NavigatorScreenParams`. > > Modal route stubs are tightened: **`TransactionDetailsSheetParams`** and **`MultichainTransactionDetailsParams`** match what those sheets actually receive (full tx/display payloads instead of optional `transactionId` only). > > Onboarding **SuccessErrorSheet** navigations now pass **`primaryButtonLabel`** instead of **`buttonLabel`**, with matching test updates—aligning call sites with the typed sheet contract. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit cb64ba0. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…ng 1 (#33461) ## **Description** In `useTokenFiatRates`, when a token's price was not found, the code was falling back to `token?.price ?? 1`, which incorrectly used `1` as a default price multiplier. This caused the fiat amount to silently return `conversionRate` instead of indicating no price is available — making it look like the token was worth 1 unit of the base currency. This fix changes the behavior to return `undefined` when `token.price` is falsy, so callers can distinguish between "price not found" and a real fiat value. The test expectation is updated accordingly. ## **Changelog** CHANGELOG entry: Fixed `useTokenFiatRates` returning an incorrect fiat amount (using conversion rate × 1) when a token price is unavailable — now returns `undefined` instead. ## **Related issues** Fixes: cherry-pick of #33447 (cp-8.3.0) ## **Manual testing steps** 1. Open MetaMask Mobile and navigate to a confirmation screen that displays token fiat amounts (e.g. a token approval or transfer). 2. Use a token whose price is **not** available in the price feed. 3. Verify the fiat amount for that token shows as unavailable/empty rather than an incorrect non-zero value. 4. Verify tokens **with** known prices still display the correct fiat amount. ## **Screenshots/Recordings** Before: <img width="530" height="1008" alt="rc - before - send" src="https://github.com/user-attachments/assets/fb3e58b9-0ae5-43b6-bcca-c39710c4c056" /> <img width="530" height="1008" alt="rc - before - mmpay" src="https://github.com/user-attachments/assets/7778b8bd-fdd1-4203-b6d5-cfcc859b2eb0" /> After: <img width="530" height="1008" alt="rc - after - send" src="https://github.com/user-attachments/assets/f11099b7-014f-4a1a-a9ef-c64701172712" /> <img width="530" height="1008" alt="rc - after - mmpay" src="https://github.com/user-attachments/assets/bcf9adce-9b26-4fe2-b56e-9165bc9f8a3c" /> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches MM Pay / confirmation amount and balance USD math when price feeds are missing; behavior is safer but users may see zero/empty conversions until prices load. > > **Overview** > Stops **confirmation pay flows** from treating a missing token price as **1** and showing a bogus fiat value (effectively `conversionRate` alone). > > **`useTokenFiatRates`** now returns **`undefined`** when `token.price` is absent instead of multiplying by a default `1`. The unit test expectation is updated from the conversion rate to **`undefined`**. > > **`useTransactionCustomAmount`** no longer falls back with `?? 1` on the pay-token fiat rate. Fiat→token conversion and USD balance helpers (`amountHuman`, `useTokenBalance` for predict / money-account withdraw) guard on a defined rate and use **`'0'`** or **`0`** when the rate is missing, while mUSD still keeps its `?? 1` fallback for money-account withdraw. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 1bb4320. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
The old patch targeted 15.11.2 while 15.15.x is installed, which aborts
yarn setup under patch-package --error-on-fail. The content-type guard
and " parser fix were never upstreamed, so the patch is regenerated
against 15.15.5 instead of removed.
<!--
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?
-->
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: null
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Fixes:
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [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**
> Patch-only dependency bump with unchanged behavioral intent; main risk
is subtle SVG/icon rendering if the patch hunk offsets drift, mitigated
by setup failing on patch apply.
>
> **Overview**
> Bumps **`react-native-svg`** from **15.15.3** to **15.15.5** in
`package.json`, `yarn.lock`, and iOS **`Podfile.lock`**, and replaces
the patch file so it applies to the installed version (fixing **`yarn
setup`** failures when **`patch-package --error-on-fail`** could not
match an outdated patch).
>
> The regenerated **`patches/react-native-svg+15.15.5.patch`** keeps the
same in-tree fixes on top of 15.15.5: reject remote SVG fetches whose
**`Content-Type`** is **`text/html`** or empty before parsing, and
normalize **`"`** to **`"`** in **`parse`** so malformed remote SVG
markup is less likely to crash the parser.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
dd657fb. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Pre-work for the RN 0.85 upgrade. 4.25.x supports RN >=0.82 on the New
Architecture and is the exact version Expo SDK 56 pairs with RN 0.85, so
landing it early keeps the final upgrade PR minimal. Main behavior
change since 4.23: iosPreventReattachmentOfDismissedScreens is enabled
by default on iOS (4.24.0).
<!--
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?
-->
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: null
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Fixes:
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [x] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Touches core navigation native code with no TS/JS diff; iOS default
screen reattachment prevention may alter dismiss/back behavior in stacks
that use RNScreens heavily (e.g. FullWindowOverlay).
>
> **Overview**
> Bumps **`react-native-screens`** from **4.23.0** to **4.25.2** in
`package.json`, with matching updates in **`yarn.lock`** and
**`ios/Podfile.lock`** (native **RNScreens** pod). No application source
changes.
>
> The lockfile now records a **`react-native` peer of `>=0.82.0`** for
this package. This is positioned as pre-work for **RN 0.85** / **Expo
SDK 56** alignment.
>
> Reviewers should treat **4.24+** as the main behavioral delta on
**iOS**: **`iosPreventReattachmentOfDismissedScreens`** is **on by
default**, which can change stack/modal dismissal and back navigation.
The app already relies on **`react-native-screens`** for navigation
primitives (e.g. **`FullWindowOverlay`**, **`enableFreeze`** in
`index.js`), so regression testing on **iOS navigation flows**
(push/pop, modals, overlays) is the main focus.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
0e302df. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
#33323) <!-- 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 --> Bumps `react-native-get-random-values` from `1.x` (resolved `1.11.0`) to `2.0.0`. **Reason:** This is required pre-work for the React Native 0.85 upgrade. RN 0.85 removes the legacy architecture entirely — there is no bridge/interop fallback. The `1.x` line registers its native module via the legacy `_RCTRegisterModule` path, which is compiled out under RN 0.85, so `1.x` fails iOS linking with an `_RCTRegisterModule` undefined-symbol error. **Solution:** `2.0.0` is a TurboModule (New Architecture) rewrite. It is New-Arch-only (peer `react-native >=0.81`), which is fine — we already run the New Architecture (bridgeless). We chose the in-place bump to `2.0.0` over migrating to `expo-crypto` because it is the smallest, lowest-risk fix for the same problem and keeps the entropy path identical. This lands on our current RN (0.83.x) now, so it gets maximum soak time before 0.85 upgrade day. It touches the wallet's random-entropy path, so it is intentionally shipped early and in isolation. It also adds a `resolutions` entry (`@segment/sovran-react-native/react-native-get-random-values: ^2.0.0`) so sovran's transitive `1.x` dependency resolves to the same `2.0.0` copy, avoiding a duplicate native module. The only consumer in our code is the side-effect polyfill import in `shim.js` (`import 'react-native-get-random-values'`), which installs `global.crypto.getRandomValues`. The public API is unchanged between `1.x` and `2.0.0`, so no source changes are required. **Files changed:** `package.json`, `yarn.lock`, `ios/Podfile.lock`. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: null ## **Related issues** <!-- mms-check: type=issue-link required=true --> Refs: RN 0.85 upgrade — PR-1 (get-random-values) in the upgrade plan ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Secure random entropy after get-random-values 2.0.0 bump Scenario: Create a new wallet (SRP generation uses crypto.getRandomValues) Given a fresh install of the app When the user creates a new wallet and completes onboarding Then a valid 12-word Secret Recovery Phrase is generated And the wallet unlocks and shows an account address Scenario: Import and unlock an existing wallet Given the app is installed When the user imports a wallet via SRP and sets a password Then the wallet unlocks successfully Scenario: Clean native build with a single native module Given a clean checkout of this branch after yarn install and pod install When the app is built and run on iOS and Android Then the build succeeds with a single react-native-get-random-values@2.0.0 native module And no _RCTRegisterModule or duplicate-module errors appear ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **High Risk** > Touches the wallet’s secure randomness path (SRP/key material) and swaps native module registration to New Architecture only; regression would affect entropy or iOS/Android native builds despite an unchanged JS API. > > **Overview** > Upgrades **`react-native-get-random-values`** from **1.x** to **2.0.0** (lockfile and iOS pods) ahead of React Native 0.85, where legacy `_RCTRegisterModule` registration is removed. Version **2.0.0** is a **New Architecture / TurboModule** implementation (peer `react-native >=0.81`), reflected in the expanded iOS pod dependency graph in **`Podfile.lock`**. > > **`package.json`** bumps the direct dependency to `^2.0.0` and adds a **`resolutions`** entry (`@segment/sovran-react-native/react-native-get-random-values: ^2.0.0`) so Segment Sovran’s transitive **1.x** copy dedupes to the same native module. **`yarn.lock`** records the resolved **2.0.0** package and updated peer range. > > No application source changes in this diff; entropy still comes from the existing side-effect import in **`shim.js`** (`global.crypto.getRandomValues`), with the same JS API between 1.x and 2.0.0. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 8c46682. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…#33214) The ContextContainer::Shared C++ alias is deprecated in RN 0.83 and removed in RN 0.85, which would break the Android native build on upgrade day. Spelling out std::shared_ptr<ContextContainer const> matches the alias definition exactly (zero behavior change on 0.83) and mirrors the RN 0.85 app template. EventDispatcher::Weak and ComponentDescriptorRegistry::Shared remain valid in 0.85 and are left untouched. <!-- 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? --> ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [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** > Single-parameter type spelling change in JNI registry setup with no logic changes; low blast radius aside from needing a successful native Android compile on upgrade. > > **Overview** > Updates the Fabric registry lambda in `MainComponentsRegistry::initHybrid` so its `contextContainer` parameter uses **`std::shared_ptr<ContextContainer const>`** instead of the removed **`ContextContainer::Shared`** alias. > > This is a compile-time compatibility fix for React Native 0.85 (alias removed) with no intended runtime behavior change on 0.83, where the alias was equivalent. **`EventDispatcher::Weak`** and **`ComponentDescriptorRegistry::Shared`** are unchanged. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 102e637. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description**
<!-- mms-check: type=text required=true -->
RN 0.85 removes the Jest preset bundled inside the `react-native`
package (`preset: 'react-native'`) — after the upgrade, every unit test
would
fail to run. The preset was extracted into a standalone
`@react-native/jest-preset` package (first published at 0.85.0).
This PR migrates us to the extracted preset ahead of the upgrade (Wave 1
of the RN 0.85 pre-upgrade PR ladder):
- Adds `@react-native/jest-preset` pinned to **0.85.3** — exactly the RN
version the upgrade targets, so the upgrade PR needs no follow-up bump
here.
- Switches `jest.config.js` `preset: 'react-native'` →
`'@react-native/jest-preset'`.
**Why this is safe on RN 0.83.6 today:** the 0.85.3 package contents
were diffed against RN 0.83.6's bundled `jest/` directory —
`resolver.js`,
`react-native-env.js`, and all mocks are byte-identical; `setup.js`
differs only in module paths being package-qualified
(`react-native/Libraries/...` instead of `../Libraries/...`), resolved
against whichever RN version is installed. No other config in the repo
uses
the old preset, and no app code imports `react-native/jest/*`. Verified
locally with 20 suites / 226 tests green (component-library,
native-mock-heavy UI components, and util suites); full unit test suite
runs in CI on this PR.
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
CHANGELOG entry: null
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Refs: <link to RN 0.85 upgrade ticket/epic>
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
Test-infrastructure-only change — no app runtime code touched. The unit
test suite itself is the verification:
```gherkin
Feature: Jest unit test suite runs on the extracted preset
Scenario: developer runs the unit test suite
Given the branch is checked out and yarn setup has completed
When the developer runs "yarn test:unit"
Then all unit tests pass identically to main
And no test setup/mock resolution errors occur
```
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
### **Before**
N/A — tooling-only change, no UI impact. Evidence is the green unit-test
CI check.
### **After**
N/A — see above.
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external
contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- [ ] I've tested with a power user scenario
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Test-tooling-only change; risk is limited to CI/local unit test
behavior, with no production app code touched.
>
> **Overview**
> Prepares for React Native 0.85 by moving unit tests off the deprecated
`preset: 'react-native'` bundled in the `react-native` package.
>
> **`jest.config.js`** now uses `@react-native/jest-preset`, with a
short comment that this matches the RN 0.85 extraction and was landed
early so the upgrade PR stays small. **`package.json`** adds
**`@react-native/jest-preset@0.85.3`** as a devDependency (aligned with
the target RN version); **`yarn.lock`** records that package and its
**`@react-native/js-polyfills@0.85.3`** dependency. No app runtime or
custom Jest setup files beyond the preset string change in this diff.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
8cbbaba. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…WebView (TMCU-1087) (#33429) ## **Description** <!-- mms-check: type=text required=true --> The Buy flow checkout opens a provider's payment page inside a native `BottomSheet`. Because we have no control over the background color of the provider's embedded webview, there is a visible mismatch between the BottomSheet surface and the provider's iframe — the native chrome looks like a container rather than a seamless extension of the checkout experience. This mismatch existed before, but the pure-black BottomSheet update (MMDS) made it significantly more jarring — particularly with Transak, one of our top providers, whose iframe uses a near-black dark background that reads as a visible border against the default sheet surface. To improve the experience we are intentionally overriding the design system BottomSheet background color to match each provider's known iframe background. This breaks the design system convention deliberately: the goal is that users should not perceive the native BottomSheet as a separate container from the provider's checkout page, making the flow feel more immersive and native. **What this PR does:** - Adds `getProviderWebviewColors(providerCode, isDark)` — a utility that maps known provider IDs (`transak`, `moonpay`, `banxa`) to their dark/light iframe backgrounds, with a safe fallback to the default MMDS BottomSheet surface for unknown providers. - Adds the three dark-mode provider hex values to `app/styles/common.ts` alongside other custom constants. - Updates both Checkout views (native Ramp and legacy Aggregator) to apply the resolved color to both the `BottomSheet` surface and the `WebView` background — so neither the sheet chrome nor the brief pre-load gap shows a mismatched color. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Improved the provider checkout experience in the Buy flow by making the BottomSheet background match the provider's embedded payment page ## **Related issues** <!-- mms-check: type=issue-link required=true --> Refs: [TMCU-1087](https://consensyssoftware.atlassian.net/browse/TMCU-1087) ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Provider checkout WebView background color Background: Given I am logged into MetaMask Mobile And I have a wallet with funds or am on testnet Scenario: Transak checkout background matches in dark mode Given I have dark mode enabled in device settings And I navigate to the Buy/Sell flow When I select Transak as my provider and proceed to checkout Then the checkout bottom sheet background should appear dark (#1a1a1a) And there should be no visible border or container around the Transak iframe Scenario: MoonPay checkout background matches in dark mode Given I have dark mode enabled in device settings And I navigate to the Buy/Sell flow When I select MoonPay as my provider and proceed to checkout Then the checkout bottom sheet background should appear dark (#131416) And there should be no visible border or container around the MoonPay iframe Scenario: Banxa checkout background matches in dark mode Given I have dark mode enabled in device settings And I navigate to the Buy/Sell flow When I select Banxa as my provider and proceed to checkout Then the checkout bottom sheet background should appear dark (#0D0D0F) And there should be no visible border or container around the Banxa iframe Scenario: Provider checkout background in light mode Given I have light mode enabled in device settings And I navigate to the Buy/Sell flow When I select any known provider (Transak, MoonPay, or Banxa) and proceed to checkout Then the checkout bottom sheet background should appear white And the provider iframe should blend seamlessly with the sheet surface Scenario: Unknown provider falls back gracefully Given I navigate to the Buy/Sell flow When I select a provider not in the known list and proceed to checkout Then the checkout bottom sheet background should match the default MMDS BottomSheet surface color And the checkout should open without any visual flash ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### Transak | Before | After | |--------|-------| | <img width="427" alt="Transak before" src="https://github.com/user-attachments/assets/60954516-b686-4413-bc30-098d339873b7" /> | <img width="423" alt="Transak after" src="https://github.com/user-attachments/assets/f84aebae-b870-4caa-8ca9-4cc5b061a453" /> | ### MoonPay | Before | After | |--------|-------| | <img width="453" alt="MoonPay before" src="https://github.com/user-attachments/assets/c53f301c-f411-4122-b55c-500a8d164c97" /> | <img width="423" alt="MoonPay after" src="https://github.com/user-attachments/assets/18f54029-2483-4d2b-bb70-fe964944b17d" /> | ### Banxa | Before | After | |--------|-------| | <img width="419" alt="Screenshot 2026-07-16 at 2 51 51 PM" src="https://github.com/user-attachments/assets/e292a074-c2b9-48eb-9350-f7aad465d160" /> | <img width="419" alt="Banxa after" src="https://github.com/user-attachments/assets/90a16331-3e42-4896-999e-89b57ee52e58" /> | ### After https://github.com/user-attachments/assets/6bbdfb84-1667-4384-9b90-83532c1de150 ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. [TMCU-1087]: https://consensyssoftware.atlassian.net/browse/TMCU-1087?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > UI-only styling in ramp checkout with no payment, auth, or order-flow logic changes; unknown providers still use the existing BottomSheet default. > > **Overview** > Buy/sell checkout **no longer uses the generic theme background** for the provider WebView and sheet chrome. A new **`getProviderWebviewColors`** helper maps known providers (Transak, MoonPay, Banxa) to their dark/light iframe colors and falls back to the default MMDS BottomSheet surface for unknown IDs. > > **Both Checkout implementations** (unified Ramp and legacy Aggregator) read the current theme, resolve `providerBg`, and apply it to the **BottomSheet** (inline `style` or `twClassName`) and the **WebView** stylesheet so pre-load flashes and visible borders against provider iframes are reduced—especially in dark mode. > > Provider-specific dark hex values were added under **`app/styles/common.ts`** for maintenance when providers change their embedded themes. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 788e4fb. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
This PR add trustline support in transaction history
It aligns the PR in
extension: MetaMask/metamask-extension#44200
core : MetaMask/core#9440
<!-- mms-check: type=text required=true -->
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: Added trustline support in transaction history
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Refs: WPN-1334
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
Txn list from asset details
<img width="354" height="748" alt="Screenshot 2026-07-20 at 11 52 11 AM"
src="https://github.com/user-attachments/assets/0e610389-9972-46a9-8ae4-8dc20bae7af7"
/>
Txn list
<img width="343" height="566" alt="Screenshot 2026-07-20 at 11 52 29 AM"
src="https://github.com/user-attachments/assets/fdbf3765-593d-4178-b33a-0181c2681d0a"
/>
Txn details modal
<img width="371" height="734" alt="Screenshot 2026-07-20 at 11 52 37 AM"
src="https://github.com/user-attachments/assets/5df078ff-8186-470e-8857-e39fc02efe18"
/>
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Changes how multichain approve/disapprove transactions are classified
and labeled in shared activity UI; scope is limited to trustline
`typeLabel`s, with solid test coverage but some regression risk if
labels are missing or wrong.
>
> **Overview**
> Adds **Stellar trustline** activate/deactivate flows to activity
history, aligned with extension/core behavior via
`transaction.details.typeLabel` (`trustline-approve` /
`trustline-disapprove`).
>
> Keyring **TokenApprove** / **TokenDisapprove** with those labels now
map to new activity kinds **`assetActivation`** and
**`assetDeactivation`** (not generic spending-cap approvals). Shared
**`trustline`** helpers drive localized titles by status; list rows,
icons, multichain transaction display, and the activity **Contract**
filter all understand the new kinds. New English copy covers
activating/deactivating trustlines and failures.
>
> Tests cover mapping, title resolution, row titles, and multichain
display; two activity list tests also call **`jest.clearAllMocks()`** in
`afterEach` so selector mock overrides do not leak.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
d90fd85. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…33409) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** <!-- mms-check: type=text required=true --> Migrates the Detox smoke notifications coverage to Appium so `SmokeNetworkAbstractions` notification onboarding runs in the Appium smoke pipeline without Metro. - Moves `enable-notifications-after-onboarding` from `tests/smoke/notifications/` to `tests/smoke-appium/notifications/` - Relocates notification mock/utils helpers under `tests/smoke-appium/notifications/utils/` and updates all consumers - Updates `NotificationMenuView` to use `Matchers.scrollContainer` so list scrolling works in both Detox and Appium ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: null ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: MMQA-1996 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Notification onboarding Appium smoke Scenario: user opens notifications and views feature and wallet notifications Given the Appium main-e2e build is installed on a simulator or emulator And notification API mocks are enabled via withFixtures When the user logs in and opens Notifications from the accounts menu Then the notification menu title is visible And the feature announcement item can be opened and closed And wallet notification items can be scrolled to, opened, and closed ``` Local validation: ```bash # iOS yarn appium-smoke:ios -- tests/smoke-appium/notifications/enable-notifications-after-onboarding.spec.ts # Android yarn appium-smoke:android -- tests/smoke-appium/notifications/enable-notifications-after-onboarding.spec.ts ``` Both platforms passed locally. ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> N/A — test-only migration; no product UI changes. ### **Before** N/A ### **After** N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. Made with [Cursor](https://cursor.com) --------- Co-authored-by: Cursor <cursoragent@cursor.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
<!-- mms-check: type=text required=true -->
Adds a full-screen **Watchlist** view reachable from the homepage
watchlist section, with edit mode to unwatch tokens, navigation to Token
Details, and instant removal UX.
### Why
Users could only see a truncated watchlist preview on the homepage. They
needed a dedicated screen to browse all watched tokens, remove items,
and open token details — without slow or janky unwatch feedback.
### What's included
**Full-screen watchlist (`WatchlistFullScreenView`)**
- New route: `Routes.WALLET.WATCHLIST_FULL_VIEW`
- Homepage watchlist section navigates to the full-screen view on tap
- Lists all watched tokens (newest first) using `useTokenWatchlistQuery`
- Header with back, Edit, Search (stub — follow-up ticket), and Done in
edit mode
- Loading skeleton while hydrated data loads
**Edit mode & unwatch**
- Edit toggles unwatch stars on each row; Done exits edit mode
- Edit auto-exits when the last item is removed
- Rows always mount `WatchlistEditableRow`; star visibility/interaction
toggles via layout + `pointerEvents` (avoids remount glitches on network
badges)
- Reanimated `FadeOut` + `LinearTransition` on a `ScrollView` + `.map()`
list for smooth removal animation
**Watchlist mutation performance**
- Optimistically updates **both** blob and hydrated React Query caches
on mutate
- Skips Token API refetch on remove/reorder (`invalidateOnSettled: {
blob: false, hydrated: false }`)
- Add still refetches hydrated metadata via `getTokens` (new tokens need
API data)
- Case-insensitive ID matching for remove operations
**TDP navigation fix**
- Passes `caipAssetId` through watchlist/trending row navigation params
- `TokenDetails` prefers route `caipAssetId` over hex→CAIP derivation
(fixes unfilled star for native EVM tokens after watchlist → TDP)
- `useTokenWatchlist` uses case-insensitive blob matching
### Deferred / out of scope
- Drag-and-drop reorder (spiked and removed; follow-up ticket planned)
- Search button wiring
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: Added a full-screen watchlist view with edit mode to
remove watched tokens
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-3121
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
```gherkin
Feature: Watchlist full-screen view
Scenario: Open full-screen watchlist from homepage
Given token watchlist feature flag is enabled
And the user has at least one token on their watchlist
When the user taps the homepage Watchlist section
Then the full-screen Watchlist view opens
And all watched tokens are displayed (newest first)
Scenario: Unwatch a token in edit mode
Given the user is on the full-screen Watchlist view with multiple tokens
When the user taps Edit
And taps the filled star on a token row
Then the row animates out immediately
And the token is removed from the list without a visible delay
And the homepage watchlist section reflects the removal after navigating back
Scenario: Navigate to Token Details from watchlist
Given the user is on the full-screen Watchlist view (not in edit mode)
When the user taps a token row
Then Token Details opens for that token
And the watchlist star shows as filled (watched)
Scenario: Edit mode exits when list is empty
Given the user is in edit mode with one token remaining
When the user unwatches that token
Then edit mode exits automatically
Scenario: TDP star toggle still works
Given the user opens Token Details from the watchlist full-screen view
When the user toggles the watchlist star off and on
Then the star state updates immediately
And returning to the watchlist list reflects the change
```
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
https://github.com/user-attachments/assets/5ac3d227-69ef-4c23-9e27-d6bcf9a3b67b
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Moderate scope: new UI plus watchlist cache/mutation behavior changes
that affect list consistency and TDP star state, but no auth or payment
paths.
>
> **Overview**
> Introduces a **full-screen Watchlist**
(`Routes.WALLET.WATCHLIST_FULL_VIEW`) opened from the homepage watchlist
section. The screen lists all watched tokens (newest first), supports
**Edit/Done** mode with per-row unwatch stars, Reanimated removal
animations, and auto-exits edit when the list is empty. Search remains a
stub for a follow-up.
>
> **Watchlist data layer** changes improve perceived performance:
mutations now optimistically update both the ID **blob** and
**hydrated** React Query caches, derive optimistic blob IDs from
hydrated data when the blob cache is cold, and **skip Token API
refetch** on remove/reorder (add still refetches hydrated metadata).
Asset ID matching for watched state and removes is **case-insensitive**.
>
> **Token Details** navigation from watchlist/trending rows now passes
optional route `caipAssetId`; `TokenDetails` prefers it when resolving
share/deeplink IDs, and `TokenDetailsSource.WatchlistFullscreen` is
added for analytics from the new screen.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
922830c. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
<!-- mms-check: type=text required=true -->
Removes the card detox test as it is migrated to appium
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry:
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Fixes: https://consensyssoftware.atlassian.net/browse/MMQA-1989
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
NA
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
NA
### **Before**
NA
### **After**
NA
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> CI and test-only changes with no app runtime impact; the sharding fix
reduces false Detox failures when Smoke tags overlap Appium suites.
>
> **Overview**
> Removes the **Detox** `SmokeMoney` card “add funds” smoke spec as that
coverage moves to **Appium**, and drops the dedicated **Android/iOS
`money-*-smoke`** Detox workflow jobs (including their rollup `needs`
entries).
>
> Updates **`e2e-split-tags-shards.mjs`** so tag-based selection no
longer treats specs under **`smoke-appium/`** as Detox-eligible. Those
Playwright+Appium tests still use `Smoke*` tags but are ignored by the
Detox Jest config; without the exclusion, CI could select them for
Detox, run zero tests, and fail.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
078b4f0. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ion (MUSD-1188) (#33491) <!-- 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? --> Navigating back from the money account card (MM Pay) to token details briefly flashed an error toast: `MetaMask Pay: Amount Update: Money Account Deposit: Cannot update transaction as ID not found`. Back navigation rejects the confirmation and removes its transaction from the `TransactionController`. A pending deposit prefill auto-submit can still run the amount update against the now-removed transaction id, which rejects with "Cannot update transaction as ID not found". `handleDone`'s catch then surfaced that failure as a toast. The fix checks the live `TransactionController` state inside `handleDone`'s catch: if the confirmation's transaction no longer exists, the update failure is a benign teardown race and the toast is suppressed. Genuine update failures (transaction still present, e.g. a reverted `previewDeposit`) still surface the toast. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Fixed an error message that flashed when navigating back from the money account card to token details. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: [MUSD-1188](https://consensyssoftware.atlassian.net/browse/MUSD-1188) ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Money account card navigation Scenario: user navigates back from the money account card to token details Given user is on the token details screen When user selects the money account card to open MM Pay And user navigates back to token details Then no error message toast is shown ``` ## **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** Error toast flashed on back navigation from the money account card to token details (see MUSD-1188). ### **After** No error toast is shown on back navigation. ## **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. [MUSD-1188]: https://consensyssoftware.atlassian.net/browse/MUSD-1188?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Narrow UX fix in confirmation error handling; genuine update failures while the transaction still exists are unchanged. > > **Overview** > Fixes a **flash error toast** when leaving MM Pay (money account card) back to token details: a late `updateTokenAmount` failure after the confirmation transaction was already removed was treated like a real update error. > > In **`handleDone`**’s `catch`, the flow now checks **`TransactionController`** for the current transaction id. If it’s gone (dismissed confirmation / back navigation), the handler **returns without showing the amount-update toast** or advancing the flow. **Real failures** while the transaction is still present still show the toast and keep the keyboard open for retry. > > Tests extend the **Engine** mock with **`TransactionController.state.transactions`**, add **`setControllerTransactions`**, and cover: toast when the tx exists on reject; **no toast** when the tracked tx was removed (including when unrelated txs remain). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 51a2431. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…red subscription (#33259) ## **Description** Predict's live hooks each spun up their own `setInterval(checkConnection, 1000)` to poll `PredictController.getConnectionStatus()` and update a local `isConnected` state. Because these hooks are mounted **per market card**, a feed with N sport/crypto cards spun up N independent 1-second timers, each walking `controller → provider → WebSocketManager` every second for a single shared global value — steady background churn that scales with list size and erodes FPS headroom during scroll. This PR replaces that per-subscriber polling with a **single push-based subscription** sourced from `WebSocketManager` (which already owns the sockets and knows connection changes at each socket's `open`/`close`): - Added `subscribeToConnectionStatus(cb)` to `WebSocketManager`, reusing its existing `Set`-based subscriber fan-out pattern. It invokes the callback immediately with the current status (correct-on-mount) and thereafter only when a channel **actually transitions** (`emitConnectionStatusIfChanged` dedups reconnect churn at the source). - Surfaced it through `PolymarketProvider` → `PredictController` (additive; `getConnectionStatus()` left untouched and still used internally). - Swapped the two timer hooks (`useLiveMarketPrices`, `usePredictGame`) to subscribe instead of poll. Net result: **N per-second timers → 0**, with connection-status behavior preserved. Scope notes: - The GitHub issue references `useLiveGameUpdates.ts`, which no longer exists — its current equivalent is `usePredictGame.ts` (same per-card timer pattern). - `useLiveCryptoPrices.ts` is left untouched: it does a one-shot check (no interval), so it is not part of the N-timers problem. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: PRED-978 Refs: #31363 ## **Manual testing steps** ```gherkin Feature: Predict live connection-status indicator Scenario: Connection indicator is correct on mount Given a live market/crypto card and a live sports game/scoreboard are open Then each card shows the correct connected state immediately, with no disconnected flash Scenario: Indicator reflects connection transitions Given a Predict live feed is open and connected When the device goes offline (airplane mode) Then the indicator flips to disconnected within a couple of seconds When the device comes back online Then the socket reconnects and the indicator flips back to connected Scenario: Shared status across many cards Given a feed with many sport and crypto cards is scrolled Then all cards show the same, correct connection state with no per-second timer fan-out ``` > Full manual QA against a **real live game** will be completed later once one is in progress; PR kept in draft until then. ## **Screenshots/Recordings** ### **Before** N/A — internal performance change; no UI/design impact. ### **After** N/A — internal performance change; no UI/design impact. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Performance-focused refactor in live UI hooks with preserved semantics, broad test coverage, and no auth or transaction changes. > > **Overview** > Replaces **per-hook 1s `setInterval` polling** of `getConnectionStatus()` in `useLiveMarketPrices` and `usePredictGame` with **`PredictController.subscribeToConnectionStatus`**, so many feed cards no longer each run their own timer. > > **`WebSocketManager`** now owns a single subscriber set: callbacks get the current status on subscribe, then updates only when sports/market/RTDS derived booleans actually change (`emitConnectionStatusIfChanged` on socket open/close/cleanup). That API is threaded through **PolymarketProvider** and **PredictController** (additive; `getConnectionStatus` unchanged). > > Hook behavior is preserved: market cards use `marketConnected`, live games use `sportsConnected`. Tests assert push-driven updates, no `setInterval`, and cleanup on unmount. **`useLiveCryptoPrices`** is out of scope (one-shot status read only). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 8996b7a. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…#33210) <!-- 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? --> Users reported latency when opening the Add bottom sheet from the Money home (MUSD-1161). Money modal sheets are presented with `animation: 'none'` + `transparentModal`, so there is no native transition: the sheet becomes visible only after the JS thread finishes mounting the component, laying it out, and starting the Reanimated slide-up. Any JS work on that path is directly visible as tap-to-sheet latency, and the sheets carried far more reactive weight than their UI needs. This PR removes that weight without changing any behavior or visuals: - **`MoneyAddMoneySheet` / `MoneyTransferSheet` no longer subscribe to the raw `TransactionController` transactions array.** They only need "is any transaction unapproved", so a new memoized boolean selector `selectHasUnapprovedTransactions` replaces `selectTransactions`. Previously every controller update (gas polling, status changes, incoming tx detection) changed the array reference and re-rendered the sheets — on wallets with large transaction histories this competes with the sheet-open animation on the JS thread. `rejectPendingTransactions` now reads the transactions from controller state at call time instead of taking the reactive array. - **`useMoneyAnalytics` (mounted by ~19 Money surfaces) no longer mounts two heavyweight hooks to compute four analytics properties.** `useMoneyAccountCardLinkage` (~15 selector subscriptions plus a side-effectful mount effect) is replaced by direct reads of the two selectors it wrapped (`selectIsMoneyAccountDelegatedForCard`, `selectIsCardAuthenticated`); the pending-link resume effect keeps running via its real consumers (`MoneyHomeView`, `MoneyOnboardingCard`, Card views). `useMoneyAccountBalance` (two React Query subscriptions whose `isFetching` flips on every 30s poll, re-rendering every consumer twice per poll) is replaced by a lazy `queryClient.getQueryState` read at event-fire time. The analytics payload contract is unchanged, including the react-query v4 disabled-query edge case; a cold cache with an existing money account reports `is_money_balance_loading: true` / `is_account_funded: null`, matching the old cold-mount behavior. The reject-and-defer pending-transaction flow in both sheets is behaviorally untouched and remains pinned by its dedicated regression suites. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Fixed latency when opening the Add and Transfer bottom sheets on the Money home. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: https://consensyssoftware.atlassian.net/browse/MUSD-1161 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Money Add / Transfer bottom sheets open without latency Scenario: user opens the Add bottom sheet Given the app is open on the Money home with a funded wallet When user taps the Add primary action Then the Add money bottom sheet slides up promptly with all options (Convert crypto, Deposit funds, Add mUSD / mUSD balance, Bank account, Receive) behaving as before Scenario: user starts a deposit while a stale unapproved transaction exists Given an unapproved transaction is pending in the background When user taps Convert crypto in the Add money bottom sheet Then the stale transaction is rejected, the sheet closes, and the deposit confirmation opens exactly as before Scenario: user opens the Transfer bottom sheet Given the app is open on the Money home with a withdrawable balance When user taps Transfer Then the Transfer bottom sheet opens promptly and Withdraw behaves as before ``` ## **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 — performance-only change, no visual changes. ### **After** N/A — performance-only change, no visual changes. ## **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** > Performance-focused refactors with regression tests for pending-tx deferral and analytics payloads; no auth or payment logic changes, but analytics balance reads at event time could diverge slightly from live UI if cache is stale. > > **Overview** > Improves **tap-to-open** responsiveness for Money **Add** and **Transfer** bottom sheets by cutting unnecessary Redux/React Query subscriptions on the mount path, without changing UI or user flows. > > **Add / Transfer sheets** now use memoized **`selectHasUnapprovedTransactions`** instead of subscribing to the full **`selectTransactions`** list and deriving pending state in-component. **`rejectPendingTransactions()`** no longer takes a transaction array; it reads the current list from **`TransactionController`** when invoked. > > **`useMoneyAnalytics`** (used across many Money surfaces) drops **`useMoneyAccountCardLinkage`** and **`useMoneyAccountBalance`** in favor of two card **selectors** and a **lazy `getQueryState`** read for balance when events fire, so background balance polling does not re-render every analytics consumer. Analytics fields (`is_account_funded`, `is_money_balance_loading`, card flags) are intended to match prior behavior, including cold-cache and error cases. > > Tests and Engine mocks were updated for the new selector, rejection helper, and analytics sourcing. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit bfb27ee. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
Opening the network selector bottom sheet triggered a cascade of **14
React render/commit cycles spanning ~550ms**. This was caused by
`FlashList` (`@shopify/flash-list`), which uses an internal
`RecyclerListView` that fires multiple `setState()` calls as it measures
and lays out items incrementally, triggering a fresh render pass for the
entire component tree on each one.
Since the network list has a bounded number of items (all
user-configured networks), virtualization provides no practical benefit
here. Replacing `FlashList` with a plain `View` + `.map()` eliminates
the cascading re-renders entirely. The 4 remaining cycles after the fix
are expected — they're driven by the React Navigation modal animation as
the sheet animates in.
| Metric | Before | After |
|---|---|---|
| Render/commit cycles on sheet open | **14 cycles** | **4 cycles** |
| React work span (sheet open) | **~550ms** | **~232ms** |
<!-- mms-check: type=text required=true -->
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: improve performance of the network selector
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-3691
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
[before.json](https://github.com/user-attachments/files/30185971/before.json)
<img width="1015" height="656" alt="image"
src="https://github.com/user-attachments/assets/c9f809ba-e5f3-4203-a6b7-eb944d8df1b0"
/>
<!-- [screenshots/recordings] -->
### **After**
[after.json](https://github.com/user-attachments/files/30185967/after.json)
<img width="1015" height="671" alt="image"
src="https://github.com/user-attachments/assets/4262dc45-14f6-4770-9b9d-b357972c4d36"
/>
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Scoped UI change in a bounded network list inside a parent
`ScrollView`; main tradeoff is losing in-list auto-scroll to the
selected network, not security or data handling.
>
> **Overview**
> **Improves network selector open performance** by removing
`@shopify/flash-list` from `NetworkMultiSelectorList` and rendering
`combinedData` with a styled `View` and `.map()` instead of a
virtualized list.
>
> **Removed list-only behavior** that came with `FlashList`: refs and
`onContentSizeChange` auto-scroll to the selected network
(`isAutoScrollEnabled` / `yOffset`), safe-area bottom padding on the
list, `getItemType`, `removeClippedSubviews`, viewability config, and
spreading extra list props onto the recycler. Keys now use a simple
`getItemKey` on each mapped row.
>
> **Tests** drop the `FlashList` mock and assert real network row
`testID`s (including empty lists via `queryAllByTestId`).
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
866b1ce. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…SD-1160) (#33195) <!-- 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? --> In the Money account activity details, the "Steps (1 completed)" heading was shown even for simple same-network mUSD transfers, where the only "step" is the transaction itself. This implied there were more actions to complete when there were none. The heading in `TransactionDetailsSummary` was gated purely on the Money account context. It now also requires more than one rendered step line (child/batch transactions, fiat order line, or source-hash line), so single-step transactions render the progress list without the heading while multi-step flows (convert/bridge withdrawals, fiat deposits, perps/predict deposits) keep it. While wiring the step count, `isSkippedTransaction` was found to match only the generic `relayDeposit` type, while the relay strategy assigns `musdRelayDeposit` to mUSD conversion deposit children. That filtered the real deposit step out of the list (and would have hidden the heading for genuine multi-step conversions), so the check now uses the shared `RELAY_DEPOSIT_TYPES` constant, consistent with the line router in the same file. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Fixed the activity details of simple mUSD transfers showing a misleading "Steps" heading ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: https://consensyssoftware.atlassian.net/browse/MUSD-1160 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Money account activity details steps heading Scenario: user views a simple same-network mUSD transfer Given the user has an mUSD Money account with a positive balance When user transfers mUSD to another account on the same network and opens the activity details Then the transaction row is shown without a "Steps" heading Scenario: user views a multi-step withdrawal Given the user has an mUSD Money account with a positive balance When user withdraws from the Money account to another token/network and opens the activity details Then the "Steps (X completed)" heading is shown above the step list ``` ## **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] --> <img width="1206" height="2622" alt="image" src="https://github.com/user-attachments/assets/051b0d0d-854c-4474-b0ba-d389321eb484" /> <img width="1206" height="2622" alt="image" src="https://github.com/user-attachments/assets/5ecf6443-78b1-4d99-b63a-8439f7ea6a90" /> ## **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** > Localized activity-details UI and step-list filtering with added tests; no auth, payments, or data-model changes. > > **Overview** > Money account activity details no longer show a **"Steps (1 completed)"** heading for simple single-step flows (e.g. same-network mUSD transfers). In Money context, the section title is omitted unless there is more than one rendered step—child/batch txs, a fiat order line, or a source-hash line—while non-Money context still uses **Summary**. > > **`isSkippedTransaction`** now treats **`musdRelayDeposit`** as a relay deposit via **`RELAY_DEPOSIT_TYPES`**, so mUSD conversion deposit children stay in the step list and multi-step conversions keep the heading and deposit line. > > The summary heading **`Text`** was switched to **`@metamask/design-system-react-native`** with **`TextColor.TextAlternative`**. Tests were expanded for multi-step, single-step, and mUSD conversion scenarios. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 75c597a. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
<!-- mms-check: type=text required=true -->
Replaces the two overlapping direction properties (trader_trade_type
auto-spread via shared props, and trade_type already in
submitted/completed tradeBaseProps) with a single trade_type key that
carries the user's actual selected mode (buy | sell) at event time.
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: null
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Fixes: https://consensyssoftware.atlassian.net/browse/TSA-900
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
NA
### **After**
NA
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> <sup>[Cursor Bugbot](https://cursor.com/bugbot) is generating a
summary for commit ea81d13. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
<!-- mms-check: type=text required=true -->
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
Updates **English** strings under
`notifications.push_notification_content` in `en.json` so wallet push
titles and bodies use shorter, consistent wording.
## **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 push notifications content
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Fixes:
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
N/A
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
N/A
### **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)
- [ ] 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**
> User-facing copy and locale key moves only; no auth, transaction, or
notification delivery logic changes.
>
> **Overview**
> Refreshes **wallet push notification** titles and bodies to shorter,
more consistent English (e.g. “You sent …” instead of “You successfully
sent …”, **Swap complete**, **Stake deposited**, trailing periods).
>
> `create-push-message.ts` now loads swap and Lido/Rocket Pool staking
titles from `notifications.push_notification_content.*` instead of
legacy top-level `notifications.*` keys; those duplicate keys are
removed across locale JSON files. Unit tests in
`create-push-message.test.ts` are updated to match the new strings.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
ea2ab1d. 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: alidotforrest <ali.forrest@consensys.net>
…USD-1180) (#33465) <!-- 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? --> The Money account Buy/deposit amount screen (`CustomAmountInfo`) now avoids two sources of per-keystroke overhead, making keypad input more responsive on device: 1. `updatePendingAmount` dispatches the `mm_pay_amount_input_type` confirmation metric only when the input type actually changes, instead of on every keypad digit. Every dispatch triggers a store-wide `useSelector` sweep across the large confirmation tree, so the previous per-digit dispatch of an unchanged `'manual'` value was pure overhead. The percentage handler re-arms the guard, so the recorded metric still always reflects the last input type used. 2. `PayWithRow` is wrapped in `React.memo`. Its only prop is a stable boolean, but it was re-rendered by the parent on every keypad digit, re-invoking its full hook cluster (including the `useAccountTokens` portfolio scan). Internal Redux/query subscriptions still re-render it whenever its own data changes. Bug: typing an amount in the Buy flow re-dispatched an unchanged metric and reconciled the payment row subtree on every digit, contributing to the sluggish input reported on iPhone Pro Max (MUSD-1180). Remaining bottlenecks in this flow (out of scope here) are tracked in the ticket: the ~4 independent `useAccountTokens` instances re-computing on polling ticks, and quote pipeline latency addressed by #33433. ## **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: Improved keypad responsiveness when entering an amount in the Money account deposit flow ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: https://consensyssoftware.atlassian.net/browse/MUSD-1180 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Money account deposit amount entry Scenario: user types a deposit amount Given the user opens the Money account and taps Add money > Deposit funds When the user types digits on the amount keypad Then each digit appears without lag and the payment row does not flicker Scenario: user mixes manual and percentage input Given the user is on the deposit amount screen When the user types digits, taps a percentage button, then types digits again Then the amount updates correctly for each input ``` ## **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 — no visual change; performance-only. ### **After** N/A — no visual change; performance-only. ## **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** > Performance-only UI changes with targeted metric deduplication; behavior is covered by new unit tests and does not alter amount calculation logic. > > **Overview** > Improves **Money deposit / custom amount** keypad responsiveness by cutting work that ran on every digit. > > **`useTransactionCustomAmount`** now dispatches `mm_pay_amount_input_type` for manual typing only when the input type changes (tracked via `lastAmountInputTypeRef`), instead of re-dispatching `'manual'` on each keystroke. That avoids repeated confirmation metric updates that were triggering broad Redux selector churn. Percentage taps still update the ref and emit metrics; switching manual → percentage → manual again still records the correct sequence. > > **`PayWithRow`** is exported as `React.memo(PayWithRowComponent)` so parent re-renders during amount entry do not re-run its hook tree when props are unchanged. > > Tests cover memo behavior on `PayWithRow` and deduplicated / mixed manual–percentage metric emissions. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 92966a5. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
<!--
mms-check directive vocabulary — read by
.github/scripts/shared/pr-template-checks.ts
at module load to build the validation plan. Directives are invisible in
rendered
markdown and must NOT be removed or edited without updating the
validator registry.
type=text Section must contain non-placeholder prose.
type=changelog Section must have a valid CHANGELOG entry: line.
type=issue-link Section must have a Fixes:/Closes:/Refs: line with a
value.
type=manual-testing Section must have real testing steps or an explicit
N/A.
type=screenshot Section must have evidence (image/URL) or an explicit
N/A.
type=checklist Section must have all checkboxes consciously checked.
required=true|false Whether a missing/invalid section runs the validator
at all.
blocking=true|false Whether a failure of this check fails the CI
workflow.
Default: false — failures are shown as warnings in the sticky
comment but do not block the PR.
Sections without a directive are checked for structural presence only.
-->
## **Description**
<!-- mms-check: type=text required=true -->
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
Show system push notifications when Android app is in foreground.
## **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: show notifications when app is in foreground on Android
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Fixes: https://consensyssoftware.atlassian.net/browse/GE-353
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
```gherkin
Feature: my feature name
Scenario: user receives push notifications
Given user has opened a Metamask application
When user is interacting with app and app is in foreground
Then user sees push notification
```
## **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**
<img width="591" height="1280"
alt="telegram-cloud-photo-size-2-5400335434266647701-y"
src="https://github.com/user-attachments/assets/e1ac2c2a-92de-4da4-a28f-4359baf2a620"
/>
### **After**
<img width="591" height="1280"
alt="telegram-cloud-photo-size-2-5400335434266647702-y"
src="https://github.com/user-attachments/assets/32e93d0c-7dca-47de-bed5-71cae9c0d52a"
/>
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [x] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Small, localized change to FCM listener lifecycle with added unit
coverage; no auth or data-path changes.
>
> **Overview**
> **Fixes Android foreground push notifications** by making the FCM
foreground subscription teardown actually clear registration state so a
new `onMessage` listener can be attached again.
>
> `#registerForegroundMessages` no longer stores the raw Firebase
unsubscribe as the “registered” flag alone: it wraps
`messaging().onMessage` in an **unsubscribe function** that calls
Firebase’s unsubscribe and then nulls `#hasRegisteredForeground` (only
when that wrapper is still the active one). Callers still get that
function from `listenToPushNotificationsReceived`, so unsubscribing
frees the single-registration guard instead of leaving a stale listener
blocked forever.
>
> Tests reset registration in `beforeEach`/`afterEach` and assert
**`onMessage` is invoked twice** after unsubscribe and a second
`listenToPushNotificationsReceived`.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
35d77e5. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…and move them above Perps title (#33361) <!-- 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 --> Deposit/withdrawal progress on Perps Home was sitting below the title balance, which made in-progress status feel disconnected from the header. This PR moves the progress bar and status row above `TitleHub`, tightens spacing, and aligns the status row with MMDS (`KeyValueRow` + `SectionDivider`). **What changed:** - `PerpsMarketBalanceActions` accepts optional `children` so title/banner content can render between the progress status and action buttons - `PerpsHomeView` nests `TitleHub` and `PerpsServiceInterruptionBanner` inside `PerpsMarketBalanceActions` so progress appears above the title - Progress status uses MMDS `KeyValueRow` / `SectionDivider` with tighter spacing - `PerpsCompetitionBanner` spacing adjusted for the new layout - Unit test covering children placement between progress status and action buttons ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Updated Perps Home so deposit and withdrawal progress appears above the account title ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: https://consensyssoftware.atlassian.net/browse/TAT-3563 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Perps Home deposit/withdrawal progress layout Scenario: user sees deposit progress above TitleHub Given the user is on Perps Home with a funded balance And a deposit is in progress When the home screen loads Then the progress bar and "deposit in progress" status appear above the Perps title/balance And Add Funds / Withdraw actions remain below the title section Scenario: user sees withdrawal progress above TitleHub Given the user is on Perps Home with a funded balance And a withdrawal is in progress When the home screen loads Then the progress bar and withdrawal status appear above the Perps title/balance And spacing between the status row, title, and competition banner looks correct ``` Also run: ```bash yarn jest app/components/UI/Perps/components/PerpsMarketBalanceActions/PerpsMarketBalanceActions.test.tsx ``` ## **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** <img width="1290" height="2796" alt="Simulator Screenshot - iPhone 15 Pro Max - 2026-07-14 at 11 48 00" src="https://github.com/user-attachments/assets/87d7e6e7-42ec-471f-b7ea-7aa88c146151" /> <img width="1290" height="2796" alt="Simulator Screenshot - iPhone 15 Pro Max - 2026-07-14 at 11 48 07" src="https://github.com/user-attachments/assets/be40e293-d4ea-40e9-a382-3e867447b3aa" /> <img width="1290" height="2796" alt="Simulator Screenshot - iPhone 15 Pro Max - 2026-07-14 at 11 48 11" src="https://github.com/user-attachments/assets/4a4718c2-63a8-427f-9240-00d7ed7d838a" /> ### **After** <img width="1290" height="2796" alt="Simulator Screenshot - iPhone 15 Pro Max - 2026-07-14 at 23 01 20" src="https://github.com/user-attachments/assets/6b94901f-6954-4e1e-9b16-d58258455837" /> <img width="1290" height="2796" alt="Simulator Screenshot - iPhone 15 Pro Max - 2026-07-14 at 23 01 23" src="https://github.com/user-attachments/assets/8e966415-0d47-4881-9e72-88c353032357" /> <img width="1290" height="2796" alt="Simulator Screenshot - iPhone 15 Pro Max - 2026-07-14 at 23 01 26" src="https://github.com/user-attachments/assets/395edd5f-358b-4b6c-8390-af918c77a9d5" /> ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Perps Home UI and layout only; funding actions unchanged but users see reordered progress—covered by expanded unit tests. > > **Overview** > Perps Home now shows **deposit/withdrawal progress above the account title** instead of below it, so in-flight funding status sits with the header. > > `PerpsMarketBalanceActions` gains optional **`children`** and **`onTitleSectionLayout`**. Progress bar, MMDS **`KeyValueRow`** / **`SectionDivider`** status row, and children (service interruption banner + **`TitleHub`** balance) share a **`TITLE_SECTION`** wrapper whose layout drives the animated header height. When balance lives in **`TitleHub`** (`hideBalanceSection`), the block still renders during initial load if children are present. > > **`PerpsHomeView`** nests banner and title inside **`PerpsMarketBalanceActions`** rather than a sibling layout above it. **`PerpsCompetitionBanner`** margins were adjusted for the new stack. Tests cover child ordering, dollar amounts, and title-section layout reporting. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 1f75b3e. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
## **Description** Adds percent-change price alerts so users can get notified when a token moves up or down by a chosen percentage over a rolling 1h or 24h window, alongside existing absolute price-target alerts. The create screen is refactored into a thin shell with an alert-type toggle (Price target / Price change) and dedicated forms (`AbsolutePriceAlertForm`, `PercentChangeAlertForm`). Shared save behavior lives in `useAlertSaveFlow`. Manage alerts lists both types, and the API layer adds `/v1/alerts/percent-change` CRUD with alert-type routing and backward-compatible normalization (alerts missing `type` default to `absolute_price`). ## **Changelog** CHANGELOG entry: Added percent-change price alerts so users can be notified when a token moves up or down by a set percentage over 1 hour or 24 hours ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-3593 ## **Manual testing steps** ```gherkin Feature: Percent-change price alerts Scenario: user creates a percent-change alert Given the user is signed in and price alerts are available for a token And the user opens Create price alert for that token When the user selects "Price change" And chooses direction (up or down), period (1hr or 24hr), and a percent threshold And optionally enables Recurring And taps Set price alert Then the alert is saved successfully And the alert appears in Manage price alerts with the correct percent summary Scenario: user creates an absolute price-target alert Given the user is on Create price alert for a token When the user leaves "Price target" selected And enters a target price (or uses a quick % pill) And taps Set price alert Then the absolute price alert is saved successfully And existing absolute-target behavior still works (including duplicate threshold messaging) Scenario: user cannot switch alert type while editing Given the user opens an existing alert in edit mode When the create/edit screen is shown Then the alert type toggle is locked to the alert's existing type And the user can update that alert's fields and save Scenario: user manages mixed alert types Given the user has both price-target and percent-change alerts for a token When the user opens Manage price alerts Then both alert types are listed with the correct titles and subtitles And the user can toggle, edit, and delete each type ``` ## **Screenshots/Recordings** ### **Before** N/A — percent-change alerts were not available (Price change was under development / placeholder). Absolute price-target create/manage unchanged in concept; attach prior screenshots if useful for comparison. ### **After** https://github.com/user-attachments/assets/13daaf6b-a6e3-452b-add3-e0bf2eee13f3 ## **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 - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Large UI refactor plus new API surface and typed alert routing; regressions could affect absolute-alert create/edit/manage or wrong endpoints for mixed alert lists, though behavior is heavily tested. > > **Overview** > Introduces **percent-change** price alerts alongside absolute price targets: users pick **Price target** vs **Price change**, set direction, rolling **1hr/24hr** period, percent threshold, and recurrence, with validation for duplicate configs and down moves over 100%. > > **Create** is refactored into a thin shell (`AlertTypeToggle`, `useAlertSaveFlow`) plus `AbsolutePriceAlertForm` and `PercentChangeAlertForm`, with shared UI (`AlertFormShell`, `AlertAmountInput`, sliding pill toggles). Absolute-target keypad/duplicate/edit behavior moves into the absolute form; parent tests focus on type switching and analytics. > > **API & types**: discriminated `Alert` union, `/v1/alerts/percent-change` CRUD, `updateAlertByType` / `deleteAlertByType`, `useSubmitPercentAlert`, and `assertOkResponse`. Route params replace `existingThresholds` with `existingAbsoluteAlerts` / `existingPercentAlerts` and optional `initialType`. > > **Manage** lists both types with formatted percent rows, passes split existing alerts into create/edit, and routes toggle/delete/update by alert type with richer analytics (`alert_period`, `alert_direction`). New i18n strings and broad unit/component-view test coverage. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 862a085. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
… tree for Toaster (#33454) ## **Description** `<Toaster />` (from `@metamask/design-system-react-native`) is wrapped in `<FullWindowOverlay>` from `react-native-screens` in `app/components/Nav/App/App.tsx`. The overlay is needed so toasts render above native-stack card screens on iOS — a plain sibling `View` cannot reach those layers. However, `react-native-screens` attaches the overlay's native container to the `UIWindow` with `accessibilityViewIsModal = YES` by default. When no toast is active (i.e. almost always), the container is empty but still marked as accessibility-modal. Per UIKit semantics, a modal AX view causes iOS to ignore every sibling view in the window — **the entire app's accessibility tree disappears**. This breaks VoiceOver for all users and any AX-based tool (XCUITest, Appium, `idb ui describe-all`, the MetaMask agent CLI, etc.). The fix adds `unstable_accessibilityContainerViewIsModal={false}` to the `FullWindowOverlay`. This prevents `react-native-screens` from setting `accessibilityViewIsModal = YES` on the native container. Toasts are non-blocking notifications, so non-modal AX behaviour is semantically correct — VoiceOver users should still be able to navigate the rest of the app while a toast is visible. The same root cause was previously introduced by `HardwareWalletProvider` (PR #32619) and fixed by conditionally mounting the overlay (PR #32973). This fix takes the simpler approach of suppressing the modal flag directly, confirmed working in the Slack thread below. **References:** - Jira: https://consensyssoftware.atlassian.net/browse/DSYS-931 - Slack thread: https://consensys.slack.com/archives/C02U025CVU4/p1783349906148579 - Related fix (HardwareWalletProvider): #32973 ## **Changelog** CHANGELOG entry: Fixes accessibility bug in with Toasts ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/DSYS-931 ## **Manual testing steps** ```gherkin Feature: iOS accessibility tree not occluded by Toaster overlay Scenario: AX tree is accessible when no toast is active Given the app is running on an iOS simulator with no active toast When idb ui describe-all is run (or VoiceOver is enabled) Then the full app accessibility tree is returned (not just the root Application node) Scenario: Toasts still render above native-stack card screens Given the app is on any screen using a native-stack navigator When a toast is triggered (e.g. via ControllerEventToastBridge) Then the toast is visually displayed above the card screen And VoiceOver can still navigate to elements behind the toast ``` ## **Screenshots/Recordings** Captured using Xcode Accessibility Inspector (target: iPhone 17 Pro Max simulator). Both states show the app rendering correctly on screen — the bug is silent to sighted users. The difference is entirely in the accessibility hierarchy panel on the left. ### **Before** The Accessibility Inspector hierarchy contains only a single `gearshape.fill (image)` node beneath the app root. Every button, label, and interactive element visible on screen — account picker, balance, Swap/Buy/Send, token list, tab bar — is completely absent from the AX tree. VoiceOver and any AX-based automation tool (XCUITest, Appium, `idb ui describe-all`) sees an effectively empty app. <img width="1508" height="957" alt="Screenshot 2026-07-16 at 4 26 13 PM" src="https://github.com/user-attachments/assets/ff4182ed-2c57-49d4-bb39-ad57b52f250f" /> ### **After** The full accessibility hierarchy is restored. The inspector lists every interactive element: `Account Fun (button)`, `Swap (button)`, `Buy (button)`, `Send (button)`, `Tokens (button)`, individual token rows (`MetaMask USD`, `Ethereum`, `Bitcoin`…), `Perpetuals (button)`, open positions, and the tab bar — matching everything visible on screen. VoiceOver and automation tools can now traverse the complete app tree. <img width="1500" height="955" alt="Screenshot 2026-07-16 at 4 27 47 PM" src="https://github.com/user-attachments/assets/e6263087-ee25-4894-afc0-8ce4f5cd5c84" /> Toasts still work as expected https://github.com/user-attachments/assets/50ee6236-d8b2-4c63-864d-b48e059ec9c4 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [\`trace()\`](/app/util/trace.ts) for usage and [\`addToken\`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Single iOS accessibility prop on the existing Toaster overlay with no auth, data, or navigation logic changes; intended to restore AX visibility without altering toast layering. > > **Overview** > Fixes an iOS accessibility regression where the **`FullWindowOverlay`** around **`<Toaster />`** in `App.tsx` caused the app’s accessibility tree to disappear for VoiceOver and AX automation when no toast was showing. > > The change sets **`unstable_accessibilityContainerViewIsModal={false}`** on that overlay so `react-native-screens` does not mark the native container as accessibility-modal, while keeping the overlay so toasts still render above native-stack cards. Inline comments document the behaviour and link **DSYS-931**. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 27085df. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** Removes the deprecated temporary `HeaderStandardAnimated` implementation from `app/component-library/components-temp/` as part of legacy design-system cleanup for accurate MMDS migration metrics. **Reason:** The temp component was a superseded duplicate marked `@deprecated` in favor of `@metamask/design-system-react-native`. **Verification before deletion:** The temp module was not imported anywhere outside its own folder (only its tests, stories, and `.storybook/storybook.requires.js`). Production callers already use MMDS, including `ActivityScreen`, Social Leaderboard views, Perps views, and `PredictHeaderStacked`. **Changes:** - Delete `app/component-library/components-temp/HeaderStandardAnimated/` (component, hook, types, tests, stories) - Remove the Storybook registration entry No runtime behavior change is expected. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: null ## **Manual testing steps** N/A — dead code removal only; production already uses MMDS `HeaderStandardAnimated`. CI unit tests are sufficient. ## **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 ## **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** > Dead-code removal only with no remaining imports of the temp module; production headers already use the design-system package. > > **Overview** > Removes the deprecated **`HeaderStandardAnimated`** shim under `app/component-library/components-temp/`, including the component, **`useHeaderStandardAnimated`** hook, types, unit tests, and Storybook stories. > > Also drops the matching entry from **`.storybook/storybook.requires.js`**. Call sites already rely on **`@metamask/design-system-react-native`**; nothing in app code imported this temp path. > > **No intended runtime or UI behavior change**—dead-code cleanup for MMDS migration metrics. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit e1c9dcd. 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: AndyMBridges <11859652+AndyMBridges@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com>
🔍 Smart E2E Test Selection⏭️ Smart E2E selection skipped - PR targets a release or stable branch (release/* or stable) All E2E tests pre-selected. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit fad67ee. Configure here.
| topInset, | ||
| translateYProgress, | ||
| ], | ||
| ); |
There was a problem hiding this comment.
Toast animation breaks on prop updates
High Severity
Resetting hasEnteredRef and dismissCompleteCalledRef when status, title, or description change does not cancel the in-flight spring/withDelay chain or restart enter when onLayout does not fire again. Transaction toasts update title asynchronously after decode, and queued same-type notifications reuse this instance after exit, so the next toast can stay off-screen and only advance via the parent fallback timeout.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit fad67ee. Configure here.
|





🚀 v8.5.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
Conduct regression and exploratory testing for your functional areas, including automated and manual tests for critical workflows.
Focus on exploratory testing across the wallet, prioritize high-impact areas, and triage any Sentry errors found during testing.
Validate new functionalities and provide feedback to support release monitoring.
GitHub Signoff
Issue Resolution
Cherry-Picking Criteria
🗓️ Timeline and Milestones
✅ Signoff Checklist
Each team is responsible for signing off via GitHub. Use the checkbox below to track signoff completion:
Team sign-off checklist
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
Note
High Risk
Release-branch cut with broad product surface in the changelog plus CI auth/token and E2E runner changes; incorrect Appium/fixture or babel/SES regressions could block releases or break network detection in production builds.
Overview
Cuts v8.5.0 (
versionName8.5.0, AndroidversionCode6291) and documents the full 8.5.0 release inCHANGELOG.md(features, changes, fixes across wallet, perps, money, notifications, etc.).CI & E2E moves more smoke coverage off Detox onto Playwright + Appium:
SmokeStake/SmokeMoneyand FixtureValidation run viarun-appium-e2e-workflow.yml; PR fixture validation and the fixture-update workflow use Appium (WDA prep,e2eenv,MM_INFURA_PROJECT_ID). Detox shard selection excludestests/smoke-appium/so tag-based splits no longer fail with zero tests. Android release builds clear incomplete NDK/SDK temp before retry. Release PR creation uses OIDC token exchange instead ofPR_TOKEN/github-tokensecrets.In-app UX & platform:
BaseNotificationis reworked with Reanimated spring enter/exit, safe-area positioning, visibility/dismiss hooks, and updated styling.BadgeWrapperaccepts optionalanchorSizefor immediate badge placement. Multichain address lists sort Stellar before Linea. Several legacy component-library pieces are removed (e.g.HeaderStandardAnimated,ListItemMultiSelectWithMenu,SelectOption,SheetActions,TextWithPrefixIcon).Build/tooling: New
@react-native/babel-presetpatch keeps Hermes from down-leveling named capture groups (SES / Infura regex fix) with a babel regression test;@metamask/bridge-controllerpatch refreshes exchange-rate fetching; old@metamask/assets-*patches dropped. BN.js migration burndown list trimmed; AndroidMainComponentsRegistryJNI signature updated for RN; scrollable tab view patch tweak; newDragGridicon.Reviewed by Cursor Bugbot for commit fad67ee. Bugbot is set up for automated code reviews on this repo. Configure here.