[pull] main from MetaMask:main#827
Merged
Merged
Conversation
…s cp-7.81.0 (#31547) ## **Description** The Perps "Learn the basics" tutorial carousel crashes on Android when navigating through the screens. **Root cause:** `ScrollableTabView` renders all child tabs simultaneously, which means 4–5 `<Rive>` components (one per tutorial screen with an animation) are all mounted with `autoplay={true}` at the same time. On Android, the Rive native renderer cannot handle multiple concurrent GPU-accelerated animation instances and crashes. **Fix:** Only mount the `<Rive>` component for the currently visible tab (`currentTab === index`). This ensures a single native Rive renderer instance exists at any time. When the user swipes or taps Continue, the previous instance is unmounted and the next one takes its place. iOS is unaffected because its Metal rendering pipeline handles concurrent Rive instances more gracefully. ## **Changelog** CHANGELOG entry: Fixed a crash on Android when navigating through the Perps tutorial carousel ## **Related issues** Fixes: #31540 ## **Manual testing steps** ```gherkin Feature: Perps tutorial carousel stability on Android Scenario: user completes the full tutorial without crash Given the user has not completed the Perps tutorial When user taps Perps and goes through "Learn the Basics of Perps" Then the app does not crash And all tutorial screens display their Rive animations correctly Scenario: user re-enters tutorial from Perps home Given the user is on the Perps home screen When user scrolls down and taps "Learn the Basics of Perps" And user taps Continue through all screens Then the app does not crash And the user reaches the final screen successfully ``` ## **Screenshots/Recordings** N/A — no visual change; this is a crash fix. The tutorial screens render identically, only one Rive animation is mounted at a time instead of all simultaneously. ### **Before** App crashes on Android when navigating through tutorial carousel screens. ### **After** Tutorial carousel completes without crash on Android. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Single conditional around Rive mounting in the tutorial carousel; behavior is unchanged except avoiding concurrent animations on Android. > > **Overview** > Fixes an **Android crash** in the Perps “Learn the basics” tutorial by ensuring only one native **Rive** animation is mounted at a time. > > `ScrollableTabView` keeps every tab’s children in the tree, so every screen with `riveArtboardName` used to mount `<Rive autoplay>` together. The change adds `index` in the screen map and renders the animation only when **`currentTab === index`**, so swiping or tapping Continue unmounts the previous instance before the next one loads. No intended UI change on iOS. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 17b73bc. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…0, MUSD-861) (#30804) ## **Description** Two small fixes for the Money tab, bundled because MUSD-861 is a pure padding tweak. **MUSD-860** — The `Add` button on the MetaMask USD row (Money home) now skips the `Add funds` bottom sheet and routes directly: if the user has mUSD balance it goes to MM Pay with mUSD pre-selected as the pay token; if not, it goes to the Ramps Buy flow with the mUSD asset pre-selected. The action-row `+` and footer `Add money` entry points still open the bottom sheet (the multi-route choice is still meaningful there). The routing logic is consolidated into a new `useMoneyAccountAddRouting` hook so `MoneyAddMoneySheet` and `MoneyHomeView` share one source of truth — no more duplicated chain-pick loop. **MUSD-861** — On the Money `Add money` confirmation screen (`MoneyAccountDepositInfo`), the `From / Pay with / Transaction fee / Est. time / Total` rows were pressed against the footer button on Android (Pixel 8a) and tall iPhones. Added an opt-in `compactSpacing` prop to the shared `CustomAmountInfo` so only `MoneyAccountDepositInfo` gets the extra bottom breathing room — Perps, Predict, musd-conversion, and Withdrawal screens are unchanged. ## **Changelog** CHANGELOG entry: Fixed the `Add` button on the Money tab to route directly to the right funding flow based on your mUSD balance, and adjusted spacing on the Money deposit screen so the rows no longer overlap the footer button on Android and tall iPhones. ## **Related issues** Fixes: [MUSD-860](https://consensyssoftware.atlassian.net/browse/MUSD-860), [MUSD-861](https://consensyssoftware.atlassian.net/browse/MUSD-861) ## **Manual testing steps** ```gherkin Feature: MetaMask USD row Add button routing (MUSD-860) Scenario: User has mUSD balance Given I am on the Money tab And my MetaMask USD balance is greater than zero When I tap "Add" next to the MetaMask USD row Then I am taken to MM Pay with mUSD pre-selected as the pay token Scenario: User has no mUSD balance Given I am on the Money tab And my MetaMask USD balance is zero When I tap "Add" next to the MetaMask USD row Then I am taken to the Ramps Buy flow with mUSD pre-selected Scenario: Action-row and footer Add still open the bottom sheet Given I am on the Money tab When I tap the central "+" action button or the footer "Add money" button Then the Add funds bottom sheet appears with the existing options Feature: Add money screen padding (MUSD-861) Scenario: Rows clear the footer Given I tap "Convert crypto" from the Add money bottom sheet When the Add money confirmation screen renders Then the From / Pay with / Transaction fee / Total rows have a clear gap above the "Add funds" footer button And no row overlaps the footer or the home indicator on Android Pixel 8a or tall iPhones ``` ## **Screenshots/Recordings** ### **Before** ### **After** https://github.com/user-attachments/assets/ca08cc77-8bc5-48ba-9fc6-116c78b91d28 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [x] I've tested on Android - [x] I've tested with a power user scenario - [x] I've instrumented key operations with Sentry traces for production performance metrics ## **Pre-merge reviewer checklist** - [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-860]: https://consensyssoftware.atlassian.net/browse/MUSD-860?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes user navigation for add-money and deposit initiation paths tied to balance and chain selection; shared confirmation UI padding affects all CustomAmountInfo screens on Android. > > **Overview** > **Money home mUSD “Add”** no longer opens the Add funds sheet. It calls **`useMoneyAccountAddRouting`**, which sends users with mUSD balance into **`moveMusd`** (deposit with `addMusd` intent and the highest-balance chain’s mUSD token) and users without balance into **Ramps Buy** via **`depositFunds`**. Analytics on that button now record **`redirect_target`** as `MONEY_DEPOSIT` vs **`RAMP_BUY`** (`SCREEN_NAMES` extended). The hook also exposes **`convertCrypto`** and is covered by unit tests; other Add entry points on the home screen still use the bottom sheet. > > **Confirmations `CustomAmountInfo`** drops the **`hasExtraBottomPadding`** prop and always applies a **`bottomBlock`** style: **16dp** bottom padding on Android (replacing the previous **56dp** opt-in used from Perps withdraw). Perps withdraw no longer passes the extra-padding flag. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 3d1671c. 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: Goktug Poyraz <omergoktugpoyraz@gmail.com>
… user has multiple wallets (#31538) <!-- 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** Display wallet name nest to From/To labels in account picker, if user has multiple wallets. ## **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/CONF-1125 ## **Manual testing steps** NA ## **Screenshots/Recordings** <img width="397" height="847" alt="Screenshot 2026-06-11 at 1 46 41 PM" src="https://github.com/user-attachments/assets/02e30963-37c5-4ed0-a913-4c94fd88208c" /> ## **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** > Localized confirmation UI label logic with unit tests; no auth, signing, or transaction flow changes. > > **Overview** > **Confirmation account picker** now shows which wallet the selected account belongs to when the user has **more than one wallet**: the pill text becomes something like `From Wallet 1` instead of plain `From`, by resolving the wallet section title from `filteredAccountSections` for the selected account group. With a single wallet, the label stays unchanged. > > Tests cover multi-wallet vs single-wallet label behavior. > > The Predict search hook test that asserted **stale markets are filtered on an empty query** was removed (active-query stale behavior test remains). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 1860ff1. 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: Nico MASSART <NicolasMassart@users.noreply.github.com>
…components (#31465) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section blocks the PR check. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> This PR updates the homepage Predictions World Cup discovery row so the “events in total” count comes from Polymarket’s lightweight pagination endpoint instead of the loaded World Cup market list. The row now uses: `https://gamma-api.polymarket.com/events/pagination?tag_slug=fifa-world-cup&limit=1&active=true&closed=false&archived=false` and reads `pagination.totalResults`. This prevents the UI from showing partial loaded counts like `19+` or `20+` when the real total is much higher. The `+` suffix is preserved. ## **Changelog** <!-- mms-check: type=changelog required=true --> <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Fixed the World Cup events count shown in the homepage Predictions discovery row. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Homepage Predictions World Cup event count Scenario: user views the World Cup discovery row in Predictions Given Predict is enabled And the homepage Predictions discovery layout is shown When the user views the FIFA World Cup 2026 row Then the row shows the total event count from the Polymarket pagination API And the count keeps the plus suffix And the row does not show a partial loaded market count such as "19+" or "20+" ``` ## **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="387" height="335" alt="Screenshot 2026-06-10 at 13 07 25" src="https://github.com/user-attachments/assets/16df1441-1e94-4bd5-a395-ba56e9aceab6" /> <!-- [screenshots/recordings] --> ### **After** <img width="391" height="337" alt="Screenshot 2026-06-10 at 12 59 32" src="https://github.com/user-attachments/assets/c163ed17-a4c7-4710-9cb5-f3ca1d2f404b" /> <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Read-only UI and a lightweight external count API; no auth, payments, or data writes. > > **Overview** > Fixes the homepage Predictions **FIFA World Cup 2026** row so “events in total” reflects Polymarket’s full catalog instead of how many markets are already loaded. > > A new **`useHomepagePredictWorldCupEventCount`** hook calls Gamma **`/events/pagination`** with `limit=1` and the remote-configured World Cup tag, then surfaces **`pagination.totalResults`** via React Query (with refetch on section pull-to-refresh). **`PredictionsSection`** loads that count alongside existing World Cup/NBA discovery feeds and treats event-count fetching as part of discovery loading. > > **`HomepagePredictWorldCupDiscovery`** stops deriving the label from `marketData.length` / `hasMore` and always formats the API total with the overflow copy (e.g. `48+ events in total`). **`MensWorldCupRow`** hides the subtitle until a count is available so partial loaded counts are not shown while the pagination request is in flight. > > Hook and section tests cover the pagination URL, invalid/missing totals, disabled queries, and the new UI assertion. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 8a68d99. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description**
Bumps `@metamask/perps-controller` from `^8.0.0` to `^8.1.0` (now
published on npm).
`8.1.0` adds human-readable market names and keyword/ranked search
(TAT-2413 / TAT-3338). Searching a market by its **full name** now
resolves to the matching market. Previously `filterMarketsByQuery` only
matched the ticker **symbol**, so searching "bitcoin", "tesla", or
"spacex" returned **"No tokens found"** even though BTC, TSLA, and SPCX
exist.
This PR also adds a `perps-market-list-no-results` testID to the
market-search empty state so the search behaviour can be asserted
directly in e2e/recipes (empty-state present for a no-match query,
absent once results appear) instead of relying on screenshots.
## **Changelog**
CHANGELOG entry: Perps market search now matches full market names and
keywords — e.g. searching "bitcoin" finds BTC (and BCH), "tesla" finds
TSLA, "spacex" finds SPCX.
## **Related issues**
Refs: TAT-2413, TAT-3338
## **Manual testing steps**
```gherkin
Feature: Perps market search by name
Scenario: user searches a market by its full name
Given the user is unlocked and on the Perps Markets search screen
When the user types "bitcoin"
Then the BTC market (and BCH "Bitcoin Cash") are listed
When the user clears and types "tesla"
Then the TSLA market is listed
When the user clears and types "spacex"
Then the SPCX market is listed
```
## **Screenshots/Recordings**
Validated end-to-end on iOS (sim `mm-4`) with a recipe using testID
assertions: the `perps-market-list-no-results` empty state is
**present** for a no-match control query and **absent** once a name
query matches.
<table>
<tr><th>Before — <code>perps-controller@8.0.0</code></th><th>After —
<code>perps-controller@8.1.0</code></th></tr>
<tr>
<td><img
src="https://raw.githubusercontent.com/abretonc7s/mm-mobile-farm-artifacts/059ffb2d33f337b829f7648eef551362ff7f8f9f/fixes/31537/before-bitcoin-8.0.0.png"
width="260"><br/>"bitcoin" → <b>No tokens found</b> (only ticker "BTC"
matched)</td>
<td><img
src="https://raw.githubusercontent.com/abretonc7s/mm-mobile-farm-artifacts/059ffb2d33f337b829f7648eef551362ff7f8f9f/fixes/31537/after-bitcoin-8.1.0.png"
width="260"><br/>"bitcoin" → <b>BTC</b> + <b>BCH</b> (matched by
name)</td>
</tr>
</table>
The name search also works for stocks and pre-IPO markets:
<table>
<tr><th>"tesla" → TSLA</th><th>"spacex" → SPCX</th></tr>
<tr>
<td><img
src="https://raw.githubusercontent.com/abretonc7s/mm-mobile-farm-artifacts/059ffb2d33f337b829f7648eef551362ff7f8f9f/fixes/31537/after-tesla-8.1.0.png"
width="260"></td>
<td><img
src="https://raw.githubusercontent.com/abretonc7s/mm-mobile-farm-artifacts/059ffb2d33f337b829f7648eef551362ff7f8f9f/fixes/31537/after-spacex-8.1.0.png"
width="260"></td>
</tr>
</table>
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [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**
> Dependency bump with localized UI/testID changes; search behavior
improves without touching auth or payments.
>
> **Overview**
> **Upgrades `@metamask/perps-controller` to 8.1.0** so Perps market
search can match **full names and keywords**, not just tickers (e.g.
"bitcoin" → BTC/BCH). Displayed market **names** now come from the
controller’s asset name map (tests expect BTC → **Bitcoin**).
>
> Adds **`perps-market-list-no-results`** on the market list
empty-search UI for e2e assertions, and a **`BACK_BUTTON`** testID alias
alongside existing list selectors. Lockfile also picks up
**`@metamask/controller-utils@12.2.0`** via the perps-controller
dependency.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
ad85672. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ve backdrop overlay (#31550) ## **Description** QuickBuy's bottom sheet previously used the full `BottomSheet` wrapper from `@metamask/design-system-react-native`, which includes a `BottomSheetOverlay` (dark backdrop) that was obscuring the asset details chart underneath. This change swaps the wrapper for `BottomSheetDialog` directly — the lower-level component that the Design System team recommends for this use case. `BottomSheetDialog` provides all the core sheet behaviour (slide-in/out animation, swipe-to-dismiss gesture, drag handle, keyboard avoidance) without rendering any backdrop overlay. The imperative ref API is updated from `onOpenBottomSheet`/`onCloseBottomSheet` to `onOpenDialog`/`onCloseDialog` accordingly. The asset details chart now remains fully visible underneath the open sheet. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: QuickBuy sheet without backdrop Scenario: User opens QuickBuy from the asset detail view Given the user is on the Asset detail view And the asset details chart is visible When the user taps the QuickBuy CTA Then the QuickBuy bottom sheet slides up without a dark overlay And the asset chart underneath remains visible When the user swipes the sheet down Then the sheet dismisses normally ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <img height="790" alt="Simulator Screenshot - iPhone 17 Pro - 2026-06-11 at 10 55 20" src="https://github.com/user-attachments/assets/ebd99ff5-b845-493a-99a0-424ea6a3511d" /> <!-- [screenshot showing dark backdrop over the chart] --> ### **After** <img height="790" alt="Simulator Screenshot - iPhone 17 Pro - 2026-06-11 at 10 51 43" src="https://github.com/user-attachments/assets/898e87e6-3fdf-41b3-b03f-27f68093febc" /> ## **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** > UI wrapper swap in a single feature with equivalent sheet behavior; tests updated and no auth, payment, or data-path changes. > > **Overview** > **QuickBuy** now uses **`BottomSheetDialog`** from the design system instead of **`BottomSheet`**, so the sheet no longer renders the dark **`BottomSheetOverlay`** backdrop and the asset chart stays visible under the open sheet. > > The imperative ref API is aligned with the dialog component: **`onOpenDialog`** / **`onCloseDialog`** replace **`onOpenBottomSheet`** / **`onCloseBottomSheet`** for deferred content readiness and animated dismiss. **`QuickBuyRoot.test.tsx`** and **`QuickBuySheet.test.tsx`** mocks and assertions were updated to match. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 7d1759a. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section blocks the PR check. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> useComplianceGate had a race condition where switching wallets could cause the previous wallet's compliance result to be applied to the new one. Between a wallet switch and the useEffect firing, gate() would read stale refs and either block a clean wallet or allow a blocked one through. The fix tags each prefetch with its address so gate can verify it belongs to the current wallet before trusting it. A latest-value ref (currentAddressKeyRef) is updated during render — before the effect fires — letting gate detect a mid-flight wallet switch and abandon silently rather than applying a stale result. A request ID counter prevents slow in-flight checks from overwriting the result for a newer address. Three new tests cover the race scenarios: stale prefetch from a previous address, silent abandon on mid-flight wallet switch, and correct blocking for the newly-selected address. ## **Changelog** <!-- mms-check: type=changelog required=true --> <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: https://consensyssoftware.atlassian.net/browse/TAT-3336 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Compliance gate respects wallet switch during pending check Scenario: user switches wallet while a compliance check is in progress Given the user has a blocked wallet and a clean wallet And the user is on the Perps screen with the blocked wallet selected And a compliance check is in flight When the user switches to the clean wallet And taps a Perps action before the check resolves Then the action is not blocked And the Access Restricted modal is not 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** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> https://github.com/user-attachments/assets/ba4f234a-3c02-4224-bc70-3d9f39e4b73b https://github.com/user-attachments/assets/aa72fb6c-f910-4943-bf0d-79334a816041 ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes compliance gating for Perps and similar flows; incorrect logic could wrongly block or allow actions, though behavior is heavily tested and fail-open on errors is preserved. > > **Overview** > Fixes a **wallet-switch race** in `useComplianceGate` so OFAC prefetch results from the previous account are not applied after the user changes wallets. > > **`useComplianceGate`** now tags each prefetch with its `addressKey`, uses a **request ID** so late responses cannot overwrite the current wallet’s blocked state, and updates **`currentAddressKeyRef` during render** so `gate()` can detect a mid-flight switch and **abandon silently** (no modal, action not run). If there is no matching prefetch yet after a switch, `gate()` runs a one-off check via `checkComplianceRef`. Empty/missing addresses are handled explicitly (`filter(Boolean)` on split addresses; no prefetch when compliance is disabled). > > **Tests** add coverage for no-address behavior and three wallet-switch scenarios (stale prefetch, abandon on switch, block on new blocked address). > > **Mock** `@metamask/compliance-controller` gets typed `ComplianceService` options and **non-EVM address lookup** aligned with the real package (no case-insensitive fallback for non-EVM). > > **`compliance-service-init.test.ts`** restores `COMPLIANCE_API_URL` in **`afterEach`** instead of `afterAll` so env isolation is per test. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 3e4e39e. 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: Nick Gambino <nicholas.gambino@consensys.net>
#31454) ## **Description** <!-- mms-check: type=text required=true --> The shared icon asset `app/component-library/components/Icons/Icon/assets/error.svg` hardcodes `fill="#121314"` on its path, which overrides the `currentColor` mechanism the `Icon` component relies on. As a result `IconName.Error` always rendered near-black at every call site (~24 across the app), regardless of the color passed. This PR removes the hardcoded fill (and the non-standard root `fill`/`width`/`height` attributes) so `error.svg` matches the structure of the other 283 icon assets and inherits the color passed to `Icon`. Among all icon assets only `error.svg` and `hash-tag.svg` had hardcoded hex fills; `hash-tag.svg` is left untouched as out of scope. Jira: [TSA-662](https://consensyssoftware.atlassian.net/browse/TSA-662) ## **Changelog** <!-- mms-check: type=changelog required=true --> CHANGELOG entry: Fixed error icons rendering black instead of the error color (e.g. in the Quick Buy failure toast) ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: [TSA-662](https://consensyssoftware.atlassian.net/browse/TSA-662) ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Error icon color Scenario: user sees a Quick Buy failure toast Given the user is on a token details page And a Quick Buy trade is going to fail terminally When the "Couldn't buy/sell" toast appears Then the leading error icon is tinted red (theme error color), matching the green icon of the success toast ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** N/A ### **After** N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- Generated with the help of the pr-description AI skill --> [TSA-662]: https://consensyssoftware.atlassian.net/browse/TSA-662?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Single SVG asset change with no logic or API changes; only visual tinting for an icon that was incorrectly fixed to black. > > **Overview** > **`error.svg`** no longer hardcodes `fill="#121314"` on its path or redundant root `fill`/`width`/`height`, so it follows the same pattern as the other icon assets and picks up **`Icon`**’s `currentColor` styling. > > **`IconName.Error`** call sites that pass theme error colors (e.g. Quick Buy failure toasts, bridge banners) should now show red/error tinting instead of always rendering near-black. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit be67024. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…ltered market list (#30738) ## **Description** Add a magnifying glass icon to the market detail screen header. Tapping it navigates to the Market List pre-filtered to the category of the market being viewed (e.g. BTC → Crypto tab, TSLA → Stocks tab). Category mapping uses the market's `marketType` field: `equity` → stocks, `commodity` → commodities, `forex` → forex, default → crypto, `isNewMarket` → all. Tracks `PERPS_UI_INTERACTION` with `button_clicked: magnifying_glass` on tap, and Market List receives `source: magnifying_glass` for `PERPS_SCREEN_VIEWED` attribution. ## **Changelog** CHANGELOG entry: Added category-aware search shortcut to market detail page ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TAT-3168 ## **Manual testing steps** ```gherkin Feature: Market detail category search shortcut Scenario: user taps magnifying glass on crypto market Given user is on the BTC market detail page When user taps the magnifying glass icon in the header Then the Market List opens with the Crypto tab pre-selected Scenario: user taps magnifying glass on equity market Given user is on the TSLA market detail page When user taps the magnifying glass icon in the header Then the Market List opens with the Stocks tab pre-selected Scenario: user navigates back from Market List Given user arrived on the Market List via the magnifying glass When user taps the back button Then user returns to the originating market detail page Scenario: new market defaults to All tab Given user is viewing a market with isNewMarket=true and no marketType When user taps the magnifying glass icon Then the Market List opens with the All tab selected ``` ## **Screenshots/Recordings** <table> <tr><td align="center" width="50%"><strong>Recipe Manual/ac1 Btc Detail Search Icon</strong><br/><img src="https://raw.githubusercontent.com/abretonc7s/mm-mobile-farm-artifacts/main/fixes/30738/recipe-manual/ac1-btc-detail-search-icon.png?sha=fd6ba732f091dab6" alt="Recipe Manual/ac1 Btc Detail Search Icon" width="400" /></td><td align="center" width="50%"><strong>Recipe Manual/ac2 Market List From Shortcut</strong><br/><img src="https://raw.githubusercontent.com/abretonc7s/mm-mobile-farm-artifacts/main/fixes/30738/recipe-manual/ac2-market-list-from-shortcut.png?sha=6e052a30c5ac05df" alt="Recipe Manual/ac2 Market List From Shortcut" width="400" /></td></tr> <tr><td align="center" width="50%"><strong>Recipe Manual/clean 1 Btc Detail</strong><br/><img src="https://raw.githubusercontent.com/abretonc7s/mm-mobile-farm-artifacts/main/fixes/30738/recipe-manual/clean-1-btc-detail.png?sha=85b4edc4666f20be" alt="Recipe Manual/clean 1 Btc Detail" width="400" /><br/><sub>caption confidence: LOW — generic filename — no state-specific suffix</sub></td><td align="center" width="50%"><strong>Recipe Manual/clean 2 Market List</strong><br/><img src="https://raw.githubusercontent.com/abretonc7s/mm-mobile-farm-artifacts/main/fixes/30738/recipe-manual/clean-2-market-list.png?sha=44ef2c287fcbdb03" alt="Recipe Manual/clean 2 Market List" width="400" /><br/><sub>caption confidence: LOW — generic filename — no state-specific suffix</sub></td></tr> <tr><td align="center" width="50%"><strong>Recipe Manual/clean 3 Back To Detail</strong><br/><img src="https://raw.githubusercontent.com/abretonc7s/mm-mobile-farm-artifacts/main/fixes/30738/recipe-manual/clean-3-back-to-detail.png?sha=5ccac78601608b27" alt="Recipe Manual/clean 3 Back To Detail" width="400" /><br/><sub>caption confidence: LOW — generic filename — no state-specific suffix</sub></td><td></td></tr> </table> ## **Validation Recipe** <details><summary>recipe.json (11 steps — navigate to BTC detail, verify search icon, tap, verify Market List with crypto tab, back navigation)</summary> ```json { "title": "TAT-3168: Market detail category search shortcut", "description": "Verifies magnifying glass icon on market detail navigates to Market List with correct category pre-selected", "validate": { "workflow": { "pre_conditions": ["wallet.unlocked", "perps.feature_enabled"], "entry": "nav-to-market-detail", "nodes": { "nav-to-market-detail": { "action": "navigate", "target": "PerpsMarketDetails", "params": { "market": { "symbol": "BTC", "name": "BTC", "price": "0", "change24h": "0", "change24hPercent": "0", "volume": "0", "maxLeverage": 100 } }, "next": "wait-detail-loaded" }, "wait-detail-loaded": { "action": "wait_for", "test_id": "perps-market-details-view", "timeout_ms": 10000, "next": "ac1-wait-search-icon" }, "ac1-wait-search-icon": { "action": "wait_for", "test_id": "perps-market-header-category-search-button", "visibility": "viewport", "timeout_ms": 10000, "poll_ms": 500, "next": "ac1-screenshot" }, "ac1-screenshot": { "action": "screenshot", "filename": "after-ac1-search-icon-visible.png", "note": "AC1: Magnifying glass icon visible in market detail header alongside expand and star icons", "claims": { "must_show": [{ "test_id": "perps-market-header-category-search-button", "visibility": "viewport" }], "must_not_show": [{ "text_contains": "Fund your wallet" }] }, "next": "ac2-press-search-icon" }, "ac2-press-search-icon": { "action": "press", "test_id": "perps-market-header-category-search-button", "next": "ac2-wait-market-list" }, "ac2-wait-market-list": { "action": "wait_for", "test_id": "perps-market-list", "timeout_ms": 10000, "next": "ac2-verify-crypto-tab" }, "ac2-verify-crypto-tab": { "action": "eval_sync", "expression": "(function(){ var route = globalThis.__AGENTIC__.getRoute(); return JSON.stringify({ onMarketList: route.name === 'PerpsTrendingView', params: route.params }); })()", "assert": { "operator": "eq", "field": "onMarketList", "value": true }, "next": "ac2-screenshot" }, "ac2-screenshot": { "action": "screenshot", "filename": "after-ac2-market-list-crypto-tab.png", "note": "AC2: Market List opened with Crypto tab pre-selected after tapping search on BTC detail", "claims": { "must_show": [{ "test_id": "perps-market-list", "visibility": "viewport" }] }, "next": "ac4-press-back" }, "ac4-press-back": { "action": "press", "test_id": "perps-market-header-back-button", "next": "ac4-wait-return" }, "ac4-wait-return": { "action": "wait_for", "test_id": "perps-market-details-view", "timeout_ms": 10000, "next": "ac4-verify-return" }, "ac4-verify-return": { "action": "eval_sync", "expression": "(function(){ var route = globalThis.__AGENTIC__.getRoute(); return JSON.stringify({ name: route.name, isMarketDetail: route.name === 'PerpsMarketDetails' }); })()", "assert": { "operator": "eq", "field": "isMarketDetail", "value": true }, "next": "done" }, "done": { "action": "end", "status": "pass" } } } } } ``` </details> ## **Validation Logs** Command: ```bash ``` <details><summary>Full output (11/11 passed)</summary> ``` Running recipe: TAT-3168: Market detail category search shortcut Pre-conditions: wallet.unlocked, perps.feature_enabled Workflow nodes: 12 Pre-conditions: PASS [nav-to-market-detail] navigate to PerpsMarketDetails — PASS [wait-detail-loaded] wait for perps-market-details-view — PASS [ac1-wait-search-icon] wait for perps-market-header-category-search-button — PASS [ac1-screenshot] AC1: Magnifying glass icon visible — PASS [ac2-press-search-icon] press perps-market-header-category-search-button — PASS [ac2-wait-market-list] wait for perps-market-list — PASS [ac2-verify-crypto-tab] eval_sync: onMarketList=true, defaultMarketTypeFilter="crypto" — PASS [ac2-screenshot] AC2: Market List with Crypto tab — PASS [ac4-press-back] press perps-market-header-back-button — PASS [ac4-wait-return] wait for perps-market-details-view — PASS [ac4-verify-return] eval_sync: route=PerpsMarketDetails — PASS Results: 11/11 passed Recipe: PASS ``` </details> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Scoped Perps UI/navigation change with existing hooks and controller helpers; no auth or payment logic touched. > > **Overview** > Adds a **search (magnifying glass) control** to the perps market detail header so users can jump to the market list with the tab that matches the current asset. > > Tapping it resolves the category via `getMarketTypeFilter(market)`, fires `PERPS_UI_INTERACTION` (`magnifying_glass` on market details), and calls `navigateToMarketList` with `source: magnifying_glass` and `defaultMarketTypeFilter` set to that category. A new header test ID, accessibility string (`perps.market_details.category_search`), and a unit test assert the navigation params. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit b608cbf. 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?
-->
Bumps `@metamask/money-account-upgrade-controller` to `2.0.5`
## **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]
```
## **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**
> Money account upgrade flows depend on delegation, keyring, and
authenticated user storage; behavior may change via the upgraded
controller and its transitive packages despite no local code edits.
>
> **Overview**
> Bumps **`@metamask/money-account-upgrade-controller`** from `^2.0.0`
to **`^2.0.5`** in `package.json` and refreshes **`yarn.lock`**
accordingly. There are **no application source changes** in this PR.
>
> The resolved **`2.0.5`** tree pulls newer transitive versions than the
previous lock, including **`@metamask/authenticated-user-storage`**
`^2.0.0` (replacing `1.0.1`), **`@metamask/delegation-controller`**
`3.0.2`, **`@metamask/delegation-core`** `2.2.1`,
**`@metamask/delegation-deployments`** `1.4.0`,
**`@metamask/keyring-controller`** `^27.0.0`, and **`@metamask/utils`**
`^11.11.0` for that controller’s dependency graph.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
450052c. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…31444) ## **Description** The Perps home screen silently hid open positions and open orders beyond the 10th. `usePerpsHomeData` sliced both lists to a hardcoded limit of 10, while `PerpsHomeView` renders them in a vertical `ScrollView` with no carousel and no "see all" page — so a wallet with 11+ open positions/orders could never reach the rest. This change makes the home screen show **every** open position and order: the cap is no longer applied by default. `positionsLimit`/`ordersLimit` become optional opt-in parameters (slice only when an explicit finite limit is passed), and the orphaned `PositionsCarouselLimit`/`OrdersCarouselLimit` constants are removed. ## **Changelog** CHANGELOG entry: Fixed the Perps home screen hiding open positions and orders beyond the 10th — all open positions and orders are now shown. ## **Related issues** Fixes: [TAT-3294](https://consensyssoftware.atlassian.net/browse/TAT-3294) ## **Manual testing steps** ```gherkin Feature: Perps home shows all open positions and orders Scenario: user with more than ten open positions/orders Given a wallet with 11 or more open perps positions and 11 or more open orders When the user opens the Perps home screen Then every open position is listed with no cut-off at 10 And every open order is listed in the Orders section with no cut-off at 10 And scrolling reaches the last entry with none hidden ``` ## **Screenshots/Recordings** | Perps home top | 11th position visible after scroll | | --- | --- | |  |  | | Scroll proof top | After proof: 11th card present | | --- | --- | |  |  | - **Live Proof recording**: [live-proof.mp4](https://raw.githubusercontent.com/abretonc7s/mm-mobile-farm-artifacts/main/fixes/31444/video/live-proof.mp4?sha=ee31c1166cf8a323) ## **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. ## **Validation Recipe** Live, replayable end-to-end recipe (`artifacts/live-proof.json`) that drives the real app on iOS: opens 11 real testnet positions, navigates to the Perps home, scrolls the list, asserts the 11th card renders (`perps-home-position-card-10` — the one the old cap hid), screenshots top + tail, then closes all positions to restore the wallet. The recording above is this recipe running. <details> <summary>live-proof.json (the 11 <code>setup-open-*</code> seed nodes are collapsed for brevity — full file in artifacts)</summary> ```json { "schema_version": 1, "title": "TAT-3294 live proof — Perps home shows all 11 open positions", "validate": { "workflow": { "entry": "gate-status", "nodes": { "gate-status": { "action": "app.status", "next": "gate-unlock" }, "gate-unlock": { "action": "metamask.wallet.ensure_unlocked", "next": "setup-clean" }, "setup-clean": { "action": "metamask.perps.close_positions", "mode": "all", "next": "setup-open-BTC" }, "setup-open-BTC": { "action": "metamask.perps.place_order", "market": "BTC", "side": "long", "amount": "10", "leverage": 10, "next": "setup-open-SOL" }, "// ...": "setup-open-{SOL,AVAX,BNB,LTC,ARB,DOGE,SUI,LINK,XRP} — same shape", "setup-open-ADA": { "action": "metamask.perps.place_order", "market": "ADA", "side": "long", "amount": "10", "leverage": 5, "next": "ac1-nav-home" }, "ac1-nav-home": { "action": "ui.navigate", "route": "PerpsMarketListView", "next": "ac1-wait-first" }, "ac1-wait-first":{ "action": "ui.wait_for", "test_id": "perps-home-position-card-0", "timeout_ms": 15000, "next": "ac1-shot-top" }, "ac1-scroll1": { "action": "ui.scroll", "test_id": "scroll-content", "delta_y": 450, "animated": true, "next": "ac1-scroll2" }, "ac1-scroll2": { "action": "ui.scroll", "test_id": "scroll-content", "delta_y": 850, "animated": true, "next": "ac1-wait-11th" }, "ac1-wait-11th": { "action": "ui.wait_for", "test_id": "perps-home-position-card-10", "timeout_ms": 15000, "intent": "PROOF: 11th card renders — the old slice(0,10) cap hid it", "next": "ac1-shot-tail" }, "teardown-close": { "action": "metamask.perps.close_positions", "mode": "all", "next": "teardown-verify" }, "teardown-verify": { "action": "metamask.perps.read_positions", "mode": "all", "next": "done" }, "done": { "action": "end", "status": "pass" } } } } } ``` </details> **Unit tests** (not a recipe — they live in the suite): `usePerpsHomeData.test.ts` covers the hook at the layer of the cap — "displays every open position/order when more than ten are open" feeds 12 → returns 12, and fails if the `slice` removal is reverted. ## **Recipe Workflow** <details> <summary>workflow.mmd</summary> ```mermaid flowchart TD gate-status --> gate-unlock --> setup-clean setup-clean -->|"11x place_order: BTC…ADA"| ac1-nav-home ac1-nav-home --> ac1-wait-first --> ac1-shot-top --> ac1-scroll1 --> ac1-scroll2 ac1-scroll2 --> ac1-wait-11th["ac1-wait-11th<br/>wait_for card-10 (PROOF)"] ac1-wait-11th --> ac1-shot-tail --> teardown-close --> teardown-verify --> done done["done<br/>end: pass"] ``` </details> [TAT-3294]: https://consensyssoftware.atlassian.net/browse/TAT-3294?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Display-only change on Perps home with optional limits preserved for other callers; main risk is slightly longer scroll lists for power users, not trading or auth logic. > > **Overview** > Fixes a bug where **Perps home** only showed the first 10 open positions and orders because `usePerpsHomeData` applied a default `slice(0, 10)` even though the screen lists everything in a vertical scroll with no “see all” flow. > > **Data behavior:** `positionsLimit` and `ordersLimit` no longer default to 10; when omitted, the hook returns the full filtered lists. Explicit numeric limits still slice for callers that need them. `PositionsCarouselLimit` / `OrdersCarouselLimit` are removed from `HOME_SCREEN_CONFIG` and documented as intentionally uncapped on home; recent activity still uses `RecentActivityLimit`. > > **UI / testing:** `PerpsHomeView` wires `testID`s on the main scroll view and on each position/order card (`perps-home-position-card-{index}`, `perps-home-order-card-{index}`) to support scroll-and-assert E2E (e.g. proving the 11th card). Unit tests in `usePerpsHomeData.test.ts` assert uncapped behavior for 12+ items and keep opt-in limit coverage. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 76c72be. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…QA-1931) (#31543) ## **Description** Adds a `run-performance` PR label so QA can force the performance E2E workflow on demand, following the same pattern as `skip-e2e` and `force-builds`. When the label is present on an internal PR, `get-requirements.yml` sets `run_performance=true`, CI re-runs via `rerun-ci-on-skipped-e2e-labels.yml`, and the `Run Performance Tests (PR)` job executes all performance tests on Android low-profile devices — even when Smart E2E Selection would skip them (e.g. no performance-relevant changes, `skip-e2e`, or `pr-not-ready-for-e2e`). Without the label, the existing Smart E2E Selection behavior is unchanged. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: Refs: MMQA-1931 ## **Manual testing steps** ```gherkin Feature: run-performance PR label Scenario: force performance tests on a PR without AI-selected tags Given an open internal PR where Smart E2E Selection returns no performance tags When the run-performance label is added to the PR Then CI is re-triggered and the Run Performance Tests (PR) job executes Scenario: default behavior without the label Given an open internal PR without the run-performance label When CI runs after a push Then performance tests only run when Smart E2E Selection selects performance tags ``` ## **Screenshots/Recordings** N/A — CI workflow change only; validation is via GitHub Actions job execution. ### **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** > Changes are limited to GitHub Actions workflow gating and documentation; no app runtime or security-sensitive code paths are modified. > > **Overview** > Adds a **`run-performance-tests`** PR label so QA can **force the PR performance E2E workflow** to run the **full Android low-profile performance suite**, even when Smart E2E Selection would skip perf tests (e.g. `ai_performance_test_tags == '[]'`, `skip-e2e`, or `pr-not-ready-for-e2e`). > > **`get-requirements.yml`** detects the label on internal (non-fork) PRs and exposes **`run_performance`**. **`ci.yml`** updates **`Run Performance Tests (PR)`** to run when `run_performance` is true **or** when Smart E2E Selection returns non-empty perf tags; a forced run passes **blank `performance_tags`** (run all) and a fixed reasoning string. **`rerun-ci-on-skipped-e2e-labels.yml`** re-triggers CI when the label is added or removed. **`LABELING_GUIDELINES.md`** documents the label and fork limitation. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 0c47b4e. 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>
…"Link card" for cardholder users (#31520) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section blocks the PR check. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> When a user already holds a MetaMask card (i.e. `isCardholder === true`) but has not yet authenticated or linked it to their Money account, the Money onboarding stepper was incorrectly showing the "Get card" flow (title and CTA) instead of the "Link card" flow. This happened because the step-2 branch condition only checked `isCardAuthenticated && !isCardLinkedToMoneyAccount`, which evaluates to `false` for unauthenticated cardholders — even though they should be prompted to link, not to get a new card. The fix introduces a single derived boolean `shouldShowLinkCardAction` that combines both conditions: - `isCardholder` — the user already owns a card (regardless of authentication state), **or** - `isCardAuthenticated && !isCardLinkedToMoneyAccount` — the user is authenticated but the card is not linked yet. Both the step-2 content (title, description, CTAs) and the analytics `handleCardCtaPress` callback now branch on `shouldShowLinkCardAction`, ensuring cardholder users are always directed to the correct "Link card" flow. ## **Changelog** <!-- mms-check: type=changelog required=true --> <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Fixed a bug where the Money onboarding stepper showed "Get card" instead of "Link card" for users who already hold a MetaMask card ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: null ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Money onboarding stepper — cardholder sees "Link card" on step 2 Scenario: Cardholder who has not authenticated their card Given the user has a MetaMask card (isCardholder = true) And the user has NOT yet authenticated their card (isCardAuthenticated = false) And the Money onboarding stepper is visible on step 2 When the user reaches step 2 of the Money onboarding stepper Then the step 2 title reads "Link your card account" (unlinked_card_account.title) And the primary CTA reads "Link card" (unlinked_card_account.cta_primary) And pressing the CTA initiates the card link flow Scenario: Authenticated cardholder with card not linked to Money account Given the user has a MetaMask card (isCardholder = true) And the user has authenticated their card (isCardAuthenticated = true) And the card is NOT linked to the Money account (isCardLinkedToMoneyAccount = false) When the user reaches step 2 of the Money onboarding stepper Then the step 2 title reads "Link your card account" And the primary CTA reads "Link card" Scenario: Non-cardholder user on step 2 Given the user does NOT have a MetaMask card (isCardholder = false) And isCardAuthenticated = false When the user reaches step 2 of the Money onboarding stepper Then the step 2 title reads "Get a card" (no_card_account.title) And the primary CTA reads "Get card" (no_card_account.cta_primary) ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** N/A ### **After** N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- Generated with the help of the pr-description AI skill --> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Scoped UI and analytics branching in Money onboarding with unit test coverage; no auth or payment logic changes. > > **Overview** > Fixes Money onboarding **step 2** so users who already hold a MetaMask card see the **Link card** experience instead of **Get card** when they are not authenticated or not linked yet. > > The component now branches on **`shouldShowLinkCardAction`** (`isCardholder` **or** authenticated with an unlinked card) for step-2 copy/CTAs and for onboarding analytics (`LINK_CARD` vs `GET_CARD`). Tests mock **`selectIsCardholder`**, expect **`card_state: 'non_cardholder'`** where appropriate, and add coverage for cardholders who are not authenticated. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit d3f6862. 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 -->
Users can see generic transaction notifications while the swap screen or
post-trade bottom sheet is already presenting the transaction state.
Those notifications compete with the post-trade modal experience and can
make the flow feel noisy.
This change adds a post-trade notification suppression helper that
registers a notification skip predicate, tracks visible post-trade
surfaces, and suppresses tracked in-flight transaction notifications
while the relevant UI is visible. `BridgeView` and
`PostTradeBottomSheet` now increment/decrement the visible surface
count, and the confirm flow wraps `submitBridgeTx` with suppression when
the post-trade modal A/B treatment is enabled.
## **Changelog**
<!-- mms-check: type=changelog required=true blocking=true -->
CHANGELOG entry: Fixed duplicate Bridge transaction notifications while
post-trade screens are visible.
## **Related issues**
<!-- mms-check: type=issue-link required=true -->
Refs: N/A
## **Manual testing steps**
<!-- mms-check: type=manual-testing required=true -->
```gherkin
Feature: Bridge post-trade notification suppression
Scenario: user submits a Bridge transaction with the post-trade modal treatment enabled
Given the Bridge post-trade modal treatment is enabled
And the user is on the Bridge screen with a valid quote
When user submits the Bridge transaction
Then the post-trade bottom sheet opens
And the app does not show a competing generic transaction notification for the submitted Bridge transaction
Scenario: user leaves Bridge post-trade UI
Given the user submitted a Bridge transaction
And the Bridge post-trade bottom sheet is visible
When user dismisses the post-trade bottom sheet or navigates away from Bridge
Then post-trade notification suppression is released for future non-Bridge surfaces
```
Additional validation:
- `yarn jest
app/components/UI/Bridge/hooks/useBridgeConfirm/useBridgeConfirm.test.ts
app/components/UI/Bridge/components/PostTradeBottomSheet/PostTradeBottomSheet.test.ts
--collectCoverage=false`
- `yarn prettier --check
app/components/UI/Bridge/utils/postTradeNotifications.ts
app/components/UI/Bridge/components/PostTradeBottomSheet/index.tsx
app/components/UI/Bridge/hooks/useBridgeConfirm/index.ts
app/components/UI/Bridge/Views/BridgeView/index.tsx`
- `git diff --check`
## **Screenshots/Recordings**
<!-- mms-check: type=screenshot required=true -->
### **Before**
N/A - notification timing/state-management change; no screenshots or
recordings captured in this thread.
### **After**
N/A - notification timing/state-management change; no screenshots or
recordings captured in this thread.
## **Pre-merge author checklist**
<!-- mms-check: type=checklist required=true -->
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [x] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Hooks into global notification skip predicates for submitted
transactions; mis-scoping could hide legitimate toasts, though
suppression is gated on visible post-trade surfaces and tracked
bridge/batch txs.
>
> **Overview**
> Adds **`postTradeNotifications`** helpers that register a global
notification skip predicate and only suppress generic transaction toasts
while Bridge post-trade UI is visible.
>
> **BridgeView** and **PostTradeBottomSheet** increment/decrement a
ref-counted “visible surface” on focus/mount cleanup. When the
post-trade modal A/B variant is on, **`useBridgeConfirm`** wraps
**`submitBridgeTx`** in **`withPostTradeNotificationSuppression`**,
which tracks submitted tx ids and temporarily skips notifications for
in-flight bridge/batch txs until surfaces are dismissed. Unit tests
cover registration, ref-counting, and failure cleanup.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
6a16760. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section blocks the PR check. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> - Bump of `@metamask/assets-controllers` dependency from `^108.4.0` to `^109.0.0` after new [core release](MetaMask/core#9078) - Removed `TransactionController:incomingTransactionsReceived` from `TokenBalancesController` since described as breaking change in the [`@metamask/assets-controllers` CHANGELOG](https://github.com/MetaMask/core/pull/9078/changes#diff-2f986b0c95bbc85106e03a1488e264023e3c500a078db85033a92e7b4da66f2fR10) ## **Changelog** <!-- mms-check: type=changelog required=true --> <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Bump `@metamask/assets-controllers` from 108.4.0 to 109.0.0 ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: add support for assets detection on Arc network ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> 1. Import SRP 2. Import private key funds account with Arc funds 3. Click on tokens 4. Add Arc network 5. Go to homepage tokens, verify the USDC on Arc network is displayed 6. Send USDC from imported account to account (with no funds) 7. Verify send transaction is confirmed 8. Go to other Account and verify the sent funds are listed on Tokens page ## **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 ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [X] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [X] I've completed the PR template to the best of my ability - [X] I've included tests if applicable - [X] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [X] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Token balance refresh timing after incoming transfers may differ because TokenBalancesController no longer reacts to incomingTransactionsReceived; verify Arc/USDC detection and post-receive balances in manual testing. > > **Overview** > Upgrades **`@metamask/assets-controllers`** from **108.4.0** to **109.0.0** (lockfile included) to pick up the latest core release, including **Arc network** asset detection support referenced in the ticket. > > Aligns with a **breaking change** in v109: **`TokenBalancesController`** no longer subscribes to **`TransactionController:incomingTransactionsReceived`**, so that event is removed from the token-balances controller messenger allowlist in **`token-balances-controller-messenger.ts`**. Incoming-tx notifications elsewhere (e.g. **`Engine`** → **`NotificationManager`**) are unchanged in this diff. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 915a6e7. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
… Sentry (#31553) ## **Description** Currently the performance E2E pipeline sends timer step durations (e.g. login time, swap time) to Sentry after each test via `publishPerformanceScenarioToSentry`. However, the BrowserStack App Profiling v2 data — which includes UI rendering (slow/frozen frames, ANRs), CPU, and memory — is fetched after all tests complete in `PerformanceReporter.onEnd()` but never forwarded to Sentry. This PR closes that gap by: 1. Extending `publishPerformanceScenarioToSentry` to accept an optional `profilingSummary` and emit the following typed Sentry measurements when present: - `profiling_slow_frames_pct` (percent) — % of slow frames (<60 fps equivalent) - `profiling_frozen_frames_pct` (percent) — % of frozen frames (>700 ms) - `profiling_anrs` (none) — ANR count - `profiling_cpu_avg_pct` / `profiling_cpu_max_pct` (percent) - `profiling_memory_avg_mb` / `profiling_memory_max_mb` (megabyte) 2. Adding `publishProfilingDataToSentry` in `PerformanceReporter` that is called after session enrichment (`mergeSessionDataIntoMetrics`) and sends a Sentry transaction per test that has profiling data. For non-BrowserStack runs (local/simulator), behaviour is unchanged — only the existing timer-step transaction is sent. For BrowserStack runs, each test also gets a profiling transaction with the above measurements. ## **Changelog** CHANGELOG entry: null ## **Related issues** Refs: MMQA-1929 ## **Manual testing steps** ```gherkin Feature: BrowserStack profiling metrics in Sentry Scenario: Run performance E2E tests on BrowserStack and verify Sentry data Given a BrowserStack performance test run completes with profiling data available When the PerformanceReporter finishes and calls publishProfilingDataToSentry Then each test that has a profilingSummary emits a Sentry transaction And that transaction contains measurements for profiling_slow_frames_pct, profiling_frozen_frames_pct, profiling_anrs, profiling_cpu_avg_pct, profiling_cpu_max_pct, profiling_memory_avg_mb, profiling_memory_max_mb And tests without profilingSummary (local runs) are not affected ``` ## **Screenshots/Recordings** N/A — infrastructure/tooling change with no UI impact. ### **Before** BrowserStack profiling data (FPS, CPU, memory) only in HTML/CSV/JSON local reports, absent from Sentry. ### **After** BrowserStack profiling data available as typed Sentry measurements on a dedicated profiling transaction per test, queryable in Sentry Performance. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - [ ] I've tested with a power user scenario - [ ] I've instrumented key operations with Sentry traces for production performance metrics ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Adds post-run Sentry uploads for BrowserStack tests (possible duplicate timer transactions alongside the existing fixture publish) and expands the performance telemetry pipeline, but changes are gated on profiling data and env-controlled Sentry settings. > > **Overview** > After BrowserStack session enrichment, **PerformanceReporter** now publishes Sentry transactions for tests that have a valid `profilingSummary`, so UI/CPU/memory profiling that previously only appeared in local reports is also sent to Sentry. > > **`publishPerformanceScenarioToSentry`** accepts optional `profilingSummary` and `testEndTimestamp`, maps BrowserStack profiling into typed Sentry measurements (`profiling_slow_frames_pct`, `profiling_frozen_frames_pct`, `profiling_anrs`, CPU/memory metrics), mirrors the summary in `extra.profiling_summary`, and anchors transaction start/end to the test end time when provided. Runs without profiling or with enrichment errors are skipped unchanged. > > Unit tests cover profiling payload shape, absence of profiling fields, and timestamp anchoring. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 0060635. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section blocks the PR check. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> 1. Empty state: When the watchlist is empty, suggests the top 5 markets by 24h volume. Each row shows the asset's live price and 24h change alongside a "+" button to add to the watchlist. 2. Expand/collapse: When the watchlist has more than 3 markets, only the first 3 are shown with a "Show X more" toggle. A "Show less" button collapses it back. 3. Watchlist filter badge: A star badge appears at the start of the market list filter row (before Crypto/Stocks/etc.) when the user has watchlist markets. Tapping it filters the list to watchlisted assets only. Mutually exclusive with category filters. When empty, we show the same default state as on perps home 4. Watchlist header chevron: The "Watchlist" section header on the home screen now has an arrow that deep-links into the full market list with the star filter pre-selected. Hidden when the watchlist is empty. ## **Changelog** <!-- mms-check: type=changelog required=true --> <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Add new empty state for Perps Watchlist ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: https://consensyssoftware.atlassian.net/browse/TAT-2725 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Perps market list filter mutual exclusivity Scenario: Watchlist deep link clears active category filter Given the market list screen is already mounted And a category filter (e.g. "Stocks") is active When the user navigates from the home watchlist header with showWatchlistOnly Then the star (watchlist) filter is turned on And the category filter is reset to "All" And all watchlisted markets are visible regardless of category Scenario: Selecting a category deactivates the watchlist filter Given the watchlist filter is active When the user taps a category badge (e.g. "Crypto") Then the category filter is applied And the watchlist filter is turned off And all markets in that category are shown Scenario: Activating the watchlist filter clears an active category Given a category filter is active When the user taps the star badge to enable the watchlist filter Then the watchlist filter is turned on And the category filter is reset to "All" Feature: Category badge screen reader labels Scenario: Screen reader announces correct category name Given a category badge is displayed (e.g. "Forex") When a screen reader focuses the badge Then it announces "Forex" And not a raw i18n key or empty string ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> https://github.com/user-attachments/assets/00278952-9e7e-478a-a84f-3afec948bdf3 ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches watchlist persistence paths and navigation params across several Perps screens; behavior is well covered by tests but scope is broad for a user-facing feature. > > **Overview** > Adds a **Perps watchlist empty state and discovery flow** across home, market list, wallet tab, and market details. > > **Watchlist UI:** `PerpsWatchlistMarkets` now accepts **suggested markets** (top volume via `getSuggestedWatchlistMarkets`), shows an empty subtitle with **+ add** rows, **show more/less** when more than three saved markets, and an optional **header chevron** (`onSeeAllPress`) to open the full list with watchlist-only mode. Suggested rows hide when the list hits **`WATCHLIST_LIMIT` (10)**. > > **Market list:** A **star filter badge** on the category row toggles watchlist-only view, **mutually exclusive** with category filters (synced in `usePerpsMarketListView` and list handlers). Empty watchlist filter reuses `PerpsWatchlistMarkets` instead of the old favorites empty copy; sort row hides while the star filter is active. > > **Actions & limits:** New **`usePerpsWatchlistActions`** centralizes add/remove with analytics and toasts; **`PerpsMarketRowItem`** gains optional **`onAddPress`**. Market details blocks favoriting at the cap with a limit toast. > > **Wallet Perps tab:** **`PerpsTabView`** (with styles/tests) shows watchlist + explore markets when there are no positions/orders, wired through **`usePerpsTabExploreData`**. > > **Supporting:** New i18n strings, test IDs, trace name `PerpsTabView`, category badge **icon mode** + required **`accessibilityLabel`**. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit fe82a1e. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…ation cp-7.81.0 (#31566) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> Updates the World Cup homepage discovery overflow copy from “events in total” to “markets in total”. This matches the product language for the overflowing World Cup market count while leaving the normal non-overflow event count unchanged. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Updated World Cup discovery copy to say markets instead of events for overflowing counts. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: World Cup discovery card copy Scenario: user sees overflowing World Cup market count Given the Predictions homepage discovery card has more World Cup items than the display limit When the user views the World Cup discovery row Then the overflow count says "{{count}}+ markets in total" ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Copy-only English localization and test assertion change with no logic or data-handling impact. > > **Overview** > Updates World Cup homepage discovery **overflow** copy from “events” to **markets** so overflowing counts match product terminology. > > The English string `predict.homepage_discovery.events_in_total_overflow` now renders `{{count}}+ markets in total` instead of `{{count}}+ events in total`. The non-overflow key `events_in_total` is unchanged. The `PredictionsSection` test expectation for the discovery row was aligned with the new copy. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit f19f028. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )