release: 7.77.0#29883
Conversation
## **Description** Updates the Polymarket adapter contract addresses used by Predict to the new `CtfCollateralAdapter` and `NegRiskCtfCollateralAdapter` values shared by Polymarket. Polymarket added new events on these adapters and will stop accepting relayed transactions through the old adapters on May 1 at 3pm UTC. Without this change, Polymarket transactions routed through the old adapters will start failing. ## **Changelog** CHANGELOG entry: Updated Polymarket adapter contracts so Polymarket prediction transactions continue working after the relayer migration. ## **Related issues** Fixes: - PRED-853 - https://consensyssoftware.atlassian.net/browse/PRED-853 ## **Manual testing steps** ```gherkin Feature: Polymarket adapter migration Scenario: user submits a Polymarket transaction after the adapter migration Given the app is running a build from this branch And the user has access to the Predict/Polymarket experience When the user submits a Polymarket transaction that uses the collateral adapters Then the app should use the updated adapter addresses And the transaction should be accepted by the relayer after the migration cutoff ``` Not run locally; constants-only configuration update. ## **Screenshots/Recordings** Not applicable. ### **Before** Not applicable. ### **After** Not applicable. ## **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 For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Low code complexity, but changes production on-chain contract targets for Polymarket claim/relay flows; incorrect addresses would cause transactions to fail. > > **Overview** > Updates Predict’s Polymarket configuration to use new `CtfCollateralAdapter` and `NegRiskCtfCollateralAdapter` contract addresses in `polymarket/constants.ts`. > > This shifts v2 claim/relay routing (as referenced by protocol `claim.standardTarget`/`claim.negRiskTarget`) to the new adapter contracts to maintain compatibility with Polymarket’s relayer migration. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 08b08be. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…29553) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** Three independent improvements to the CI pipeline: - E2E merge gate fix: Gate now checks build jobs too (build-android-apks, build-ios-apps). Previously a failed build caused smoke tests to skip, which the gate treated as passing. This will avoid PRs getting merged with broken builds like: https://github.com/MetaMask/metamask-mobile/actions/runs/25074016847 - Yarn cache: Added node_modules + .yarn/install-state.gz caching to component-view-tests, merge-unit-and-component-view-tests, and setup-e2e-env. Saves ~2–4 min on cache hits. - Label rename: skip-e2e-quality-gate → skip-e2e-flakiness-detection. Post-merge: rename the label manually in GitHub repo settings. - Time-gated auto-labeling: The pr-not-ready-for-e2e label is now only auto-applied to new PRs opened between 13:00–17:00 UTC (15:00–19:00 CEST / 9:00–13:00 EDT), targeting the Europe–US East Coast overlap window. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- 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 - [ ] 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 - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Modifies CI workflow gating and label-driven behavior that can block or permit merges, so misconfiguration could affect release throughput. Changes are scoped to GitHub Actions/scripts and caching, with no app runtime impact. > > **Overview** > **CI merge gating is tightened for E2E** by treating failures/cancellations in `build-android-apks` and `build-ios-apps` as merge-blocking (previously a failed build could cause smoke tests to skip and still pass the gate), while still allowing intentional `skipped` outcomes when E2E is not expected to run. > > **Dependency caching is expanded** by caching `node_modules` plus `.yarn/install-state.gz` in the shared `setup-e2e-env` action and in `ci.yml` jobs that run component-view tests and coverage merge, skipping `yarn install` on cache hits. > > **Labeling/controls are updated**: `skip-e2e-quality-gate` is renamed to `skip-e2e-flakiness-detection` across scripts, rerun triggers, and docs; `auto-label-not-ready-for-e2e` is time-gated (13:00–17:00 UTC) before applying `pr-not-ready-for-e2e`; and documentation/ownership is updated (adds QA ownership for `E2E_DECISION_TREE.md` and clarifies `skip-e2e` as an exceptional “skip builds + all E2E” escape hatch). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit ede188d. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…ilds. (#29390) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** Adds automated build environment display to RC and production builds. Captures actual environment values used during builds (METAMASK_ENVIRONMENT, METAMASK_BUILD_TYPE, API URLs, etc.) and displays them: - RC builds: In PR comment alongside build links - Prod builds: Extracted via new workflow (Slack notification in follow-up PR). **Changes:** - scripts/apply-build-config.js: Add --write-build-env flag to generate build-env.json with actual env values - build.yml: Generate and upload build-env.json as artifact during builds (used by both RC and prod) - build-rc-auto.yml: Download build-env artifacts in post-rc-build-comment job - scripts/build-announce/: Add env section to RC build PR comments - prod-build-env-notify.yml: New workflow triggered on prod build completion, extracts env values (Slack posting in follow-up PR) <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MMQA-1108 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes CI build workflows and the RC PR-comment pipeline to generate, upload, download, and parse a new `build-env.json` artifact; misconfiguration could break build jobs or PR comment posting. Risk is limited to CI/reporting paths and is largely non-blocking (`continue-on-error`/`|| true`) but still touches release build automation. > > **Overview** > Adds generation of a `build-env.json` file during CI builds (via `scripts/apply-build-config.js --write-build-env`) and uploads it as a build artifact for each platform. > > Updates RC automation to download these artifacts and extends `scripts/build-announce` to parse them and include a **Build Environment** section (env/build type, remote FF mapping, key API URLs/flags) in the RC PR comment, with a fallback “not available” section on extraction failure. > > Introduces a new `Prod Build Env Notify` workflow that triggers on successful production workflow runs, downloads the `build-env` artifact, extracts key values with `jq`, and currently prints a placeholder for a future Slack notification; also ignores local `build-env.json` via `.gitignore`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 0f0c4b5. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** This PR updates the post-#29305 CI requirement filters so locale translation JSON changes are treated as E2E-ignorable. Locale-only PRs under `locales/languages/**/*.json` should now skip Smart E2E selection plus Android/iOS E2E builds and smoke tests. The change also adds the same locale rule to the Android/iOS platform-or-ignorable filters, so mixed platform + locale changes keep platform-specific E2E behavior instead of expanding to both platforms. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: MCWP-440 ## **Manual testing steps** ```gherkin Feature: CI requirements for locale translation changes Scenario: locale translation PR skips E2E Given a pull request changes only files under locales/languages/**/*.json When the ci workflow runs get-requirements Then Smart E2E selection is skipped And Android E2E build and smoke test jobs are skipped And iOS E2E build and smoke test jobs are skipped And pr-not-ready-for-e2e does not block merge for the ignorable-only change ``` ## **Screenshots/Recordings** ### **Before** N/A ### **After** N/A ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.
…-1778) (#29576) ## **Description** Tier 2 of MMQA-1364 (allowlist reduction). Adds default mock matchers for three categories of static asset / health-check requests, then removes the corresponding entries from `mock-e2e-allowlist.ts`. | Matcher | Response | | --- | --- | | `^https://clients3\.google\.com/generate_204$` (HEAD) | `204 No Content`, empty body | | `^https://raw\.githubusercontent\.com/MetaMask/contract-metadata/[^/]+/images/.+\.svg$` (GET) | `200`, minimal `<svg xmlns="http://www.w3.org/2000/svg"/>` | | `^https://token\.api\.cx\.metamask\.io/assets/nativeCurrencyLogos/.+\.svg$` (GET) | `200`, minimal SVG | **Why regex, not exact URLs.** The previous allowlist enumerated five specific token icons that today's specs happened to load. Any new spec, new default token, branch rename (`master` → `main`), or platform-subset divergence would reintroduce live requests. Regex matchers cover the entire category (any branch, any future token icon) with one entry — a one-time fix instead of a moving target. **`generate_204` origin.** Confirmed it is fired by `@react-native-community/netinfo`'s `InternetReachability._checkInternetReachability` via JS-layer `fetch`. That path is patched by `shim.js`, so the request reaches mockttp at `/proxy?url=…` and the matcher fires. (Method is `HEAD`, hence the new `HEAD` field on `DEFAULT_MOCKS`.) ### Files changed - `tests/api-mocking/mock-responses/defaults/static-assets.ts` — new default mock file with the three matchers - `tests/api-mocking/mock-responses/defaults/index.ts` — imported and spread into `DEFAULT_MOCKS.GET` + new `HEAD` field - `tests/api-mocking/mock-e2e-allowlist.ts` — removed 7 entries (1 generate_204, 5 GitHub raw token SVGs, 1 token.api nativeCurrencyLogos ethereum.svg) ### Out of scope - `https://api.avax.network/ext/bc/C/rpc` — Tier 4 investigation - `https://metamask.github.io/test-dapp/metamask-fox.svg` — handled by MMQA-1367 - Polymarket hosts — separate follow-up tracked in MMQA-1755 ## **Changelog** CHANGELOG entry: null ## **Related issues** [MMQA-1778](https://consensyssoftware.atlassian.net/browse/MMQA-1778) — parent epic [MMQA-1364](https://consensyssoftware.atlassian.net/browse/MMQA-1364) ## **Manual testing steps** ```gherkin Feature: Static asset mocks for E2E tests Scenario: NetInfo reachability probe is mocked Given the E2E mock server is running with default mocks loaded When the app fires the NetInfo reachability probe (HEAD https://clients3.google.com/generate_204) Then mockttp returns 204 with empty body And validateLiveRequests() does not record a live request Scenario: Token icon SVGs are mocked Given a spec loads a token list that includes contract-metadata icons When the app requests https://raw.githubusercontent.com/MetaMask/contract-metadata/<branch>/images/<token>.svg Then mockttp returns 200 with a placeholder SVG And the request never reaches GitHub live Scenario: Native currency logo SVGs are mocked Given a spec loads a chain whose native currency logo is fetched from token.api When the app requests https://token.api.cx.metamask.io/assets/nativeCurrencyLogos/<chain>.svg Then mockttp returns 200 with a placeholder SVG And the request never reaches the live token.api endpoint ``` ## **Screenshots/Recordings** ### **Before** `tests/api-mocking/mock-e2e-allowlist.ts` allowlisted 7 entries that bypassed `validateLiveRequests()`: What this meant on every E2E run: - NetInfo's reachability probe fired a live `HEAD https://clients3.google.com/generate_204` and Google answered. The allowlist silenced the warning, so `validateLiveRequests()` did not flag it. - 5 GitHub raw SVG fetches went live whenever notifications rendered token icons (USDC/SHIB/USDT/stETH/rETH from the mocked notification fixtures in `@metamask/notification-services-controller`). - 1 `token.api` SVG went live whenever the Ethereum native-currency logo was loaded (referenced in `app/constants/urls.ts:144` and the Ramp Quotes constants). ### **After** Allowlist with the 7 entries gone — `ALLOWLISTED_URLS` drops from 16 to 9: What happens on every E2E run now: - **NetInfo reachability probe** → mockttp returns `204` with empty body. NetInfo's `reachabilityTest` (`response.status === 204`) passes; the wallet sees the network as reachable. No live request to Google. - **Notification SVG fetches** → mockttp returns a placeholder SVG (`<svg xmlns="http://www.w3.org/2000/svg"/>`). Icons render (visual fidelity not asserted in E2E). No live request to `raw.githubusercontent.com` for any token icon — current or future. - **Native currency logo fetch** → same placeholder SVG. No live request to `token.api.cx.metamask.io` for any chain's logo. - `validateLiveRequests()` records **zero** leaks for these endpoints. ## **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 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. [MMQA-1778]: https://consensyssoftware.atlassian.net/browse/MMQA-1778?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: changes are confined to the E2E mocking layer, replacing live allowlisted static/health-check requests with deterministic mocks (including adding default `HEAD` mocks). > > **Overview** > Reduces E2E live network allowlisting by removing specific static/health-check URLs (Google `generate_204` and token SVG icon URLs) from `mock-e2e-allowlist.ts` and handling them via default mocks instead. > > Adds `STATIC_ASSETS_MOCKS` with regex-based matchers that return a `204` for `HEAD https://clients3.google.com/generate_204` and a minimal SVG for GitHub contract-metadata and `token.api` native currency logo `.svg` requests, and wires these into `DEFAULT_MOCKS` (including a new `HEAD` entry). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 7c90df2. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Claude Opus 4.7 (1M context) <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.
-->
## **Description**
On iOS<16, Detox’s device.sendToHome() brings the home screen to the
front. On iOS 16 and later, that path is not used the same way from the
simulator tooling, so Detox instead launches and immediately quits the
Settings app to put the app under test in the background. That can
briefly show Settings and race the next step.
This PR tightens tests/smoke/swap/swap-deeplink-smoke.spec.ts: a 1
second wait after sendToHome() before launchApp({ url }), newInstance:
false on those launchApp calls so the flow is clearly “same app
instance, URL delivered after background,” and short comments above each
wait explaining the pre‑16 vs 16+ behavior.
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry:
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
<!--
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
- [ ] 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**
> Test-only changes that adjust Detox app launching behavior and add
additional HTTP mocks; low risk to production code, with minor risk of
masking real integration issues if mock matching is too broad.
>
> **Overview**
> Stabilizes swap deeplink smoke tests on iOS by adding a short
post-`sendToHome()` delay and launching deeplinks with `newInstance:
false` to ensure URLs are delivered to the existing app instance.
>
> Expands swap E2E mocking by introducing reusable
`setupSwapSocialAndComplianceMocks()` to stub the Social leaderboard and
compliance batch endpoints, wiring it into swap and trending-token smoke
setups. Also tightens the swap proxy URL interception so the
`insufficientBal` rewrite only targets JSON `getQuote` requests (not
`getQuoteStream`).
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
edbfe2c. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
… re-renders (#29597) ## **Description** Inline `[]` fallbacks in `useWithdrawalRequests` selectors were creating new array references on every render, triggering React-Redux's "Selector unknown returned a different result" warning and causing unnecessary re-renders in `PerpsProgressBar` on mount. Fixed by replacing inline `[]` literals with module-level constants and short-circuiting `.filter()` on empty arrays so selectors always return the same reference. **Performance impact:** FPS on Perps tab mount improved from 60→22 drops down to a stable 60→57, nearly eliminating the frame drop entirely and it doesn't take ~1 second for the Perps screen to show anymore **NOTE**: Unrelated to these changes, there is a considerate amount of frame drop when you're on the Perps home screen and from the UI hydrating. The frames drop as low as 8 FPS. This happens in `main` and this branch as well. Might be worth a follow up ticket ## **Changelog** CHANGELOG entry:null ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: Perps home screen mount Scenario: user opens the app with Perps hub tab visible Given the hub tabs A/B test is enabled And the user has no pending withdrawal requests When the app loads and PerpsProgressBar mounts Then no "Selector unknown returned a different result" warning appears in the console And the Perps tab renders without unnecessary re-renders And FPS remains at or above 57 during mount ``` ## **Screenshots/Recordings** https://github.com/user-attachments/assets/76f6b555-a949-4633-8d4c-aaffffb23f65 ### **Before** https://github.com/user-attachments/assets/4fb102b9-2dac-48c6-9b10-bbe6316825d2 ### **After** https://github.com/user-attachments/assets/4c6688dd-159c-4e9e-89ef-c298de8bc34c ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk performance-only change: replaces inline empty-array fallbacks with stable module constants to avoid React-Redux selector warnings and unnecessary re-renders; no business logic or API behavior changes expected. > > **Overview** > Prevents unnecessary re-renders in `useWithdrawalRequests` by replacing inline `[]` selector fallbacks with module-level `EMPTY_WITHDRAWAL_REQUESTS`/`EMPTY_TX_HASHES` constants and short-circuiting the withdrawal `.filter()` when there’s no selected address or the list is empty. > > This makes selector outputs stable across renders (eliminating the “selector returned a different result” warning) while keeping the displayed/polled withdrawal logic unchanged. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit e020446. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Reverts #29377 Shouldn't need double zip anymore since Runway should support .app bundles <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk because it changes CI artifact packaging and paths for iOS simulator outputs, which could break downstream consumers or uploads if the expected zip naming/location differs. > > **Overview** > Reverts the iOS simulator artifact workaround that **double-zipped and staged** `.app` bundles before upload, returning to a single `.zip` produced directly from the simulator `.app` and emitting that path via `ios_simulator_path`. > > The build workflow is simplified by removing simulator upload staging/cleanup logic and loosening the upload step condition (dropping the redundant `success()` guard). The artifact renaming script also switches from `execFileSync` to `execSync` for `find`/`cp`/`ditto` invocations and removes repo-relative path conversion for simulator uploads. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 255c3e0. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description**
Follow-up to the BigInt introduction PR (which adds
`app/util/number/bigint.ts` and marks the helpers in
`app/util/number/index.js` as `@deprecated`). That PR provides the
replacement API; this PR puts the guardrails in place so the migration
becomes a one-way ratchet — the count of legacy `app/util/number`
importers can only go down from here.
**What this PR adds**
1. **`@typescript-eslint/no-deprecated: 'warn'`** in `.eslintrc.js` for
all `*.{ts,tsx}` files. Surfaces a warning at every use-site of any
helper already annotated `@deprecated` (the `app/util/number` exports
today, plus anything else marked deprecated in the future).
2. **`no-restricted-imports` fence** on `app/util/number` /
`app/util/number/index` for `app/**/*.{ts,tsx,js,jsx}`. New imports are
a **hard error** pointing the developer at `app/util/number/bigint`.
Existing importers (107 files at the
time of writing) live in a top-level `utilNumberImportBurndownFiles`
constant in `.eslintrc.js`. Entries should be **removed** as files are
migrated, never added. Two override blocks are needed because ESLint's
`excludedFiles` applies to the whole override, not per-rule. A single
combined block would silently exempt the burn-down files from the
existing `expo-haptics` and `**/controllers/perps` fences too. The first
override holds all three fences and excludes the burn-down list; the
second override re-applies only `expo-haptics` and perps to the
burn-down files.
3. **`app/util/number/**` is also excluded** so the legacy module and
its parity tests can keep importing each other for migration parity
comparisons.
4. **CODEOWNERS** entry: `app/util/number/index.js` is now owned by
`@MetaMask/mobile-platform`. Any change to the deprecated module (e.g.
adding a new export, modifying an existing helper) requires platform
review. Scope is intentionally limited to the deprecated file —
`bigint.ts` and the tests are not gated.
5. **Deletion of `calcTokenValueToSend`** from
`app/util/number/index.js` (and its test). The function was dead code
(only referenced by its own test).
**Why all three layers?**
| Layer | Catches |
| -------------------------------- |
----------------------------------------------------------------- |
| `@typescript-eslint/no-deprecated` (warn) | Every existing call-site
of a deprecated helper, even within the allowlist. |
| `no-restricted-imports` (error) | Any **new** file that tries to
import from the deprecated module. |
| CODEOWNERS | Any change to the deprecated module itself (new exports,
edits). |
The combination gives a one-way ratchet: warnings flag what to migrate,
the import fence prevents new debt, and CODEOWNERS prevents the legacy
module from quietly growing.
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry:null
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
<!--
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**
> Primarily tooling/guardrail changes, but new ESLint fences and
deprecated-use warnings can break builds for newly added/modified
imports and may require follow-up fixes across many files as migration
progresses.
>
> **Overview**
> Adds **migration guardrails** for the BN.js → BigInt transition by
enabling `@typescript-eslint/no-deprecated` (warn) and introducing an
ESLint import fence that blocks new imports resolving to deprecated
`app/util/number/index.js`, with a temporary allowlisted burndown set.
>
> Updates `CODEOWNERS` to require platform review for changes to the
deprecated `app/util/number/index.js`, expands documentation with a
burndown-by-team section, and links the migration guide from the main
`README`.
>
> Removes the unused `calcTokenValueToSend` helper (and its test) from
the legacy number module, and increases Node memory limits for
`lint`/`tsc` scripts to reduce OOMs.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f2197ad. 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: Cal-L <cal.leung@consensys.net>
Co-authored-by: tommasini <tommasini15@gmail.com>
Co-authored-by: tommasini <46944231+tommasini@users.noreply.github.com>
## **Description**
HyperLiquid is deprecating DEX Abstraction mode (~May 9). This PR forces
every Perps user onto **Unified Account** mode on app open and fixes the
withdraw + balance-display flows that were broken in the target state.
### 1. Forced migration to Unified Account
Migration paths by current abstraction mode:
- `default` / `disabled` → silently migrated via `agentSetAbstraction({
abstraction: 'u' })` — no signing prompt
- `dexAbstraction` → one-time EIP-712 prompt via `userSetAbstraction({
user, abstraction: 'unifiedAccount' })` — agent-key path is blocked by
HL for this transition
- `unifiedAccount` → no-op, cached immediately
Key details:
- Replaces deprecated `agentEnableDexAbstraction` / `userDexAbstraction`
with `agentSetAbstraction` / `userSetAbstraction` / `userAbstraction`
- Runs on perps section open (`#ensureReady()`) so users are set up
before trading
- `TradingReadinessCache` prevents repeated prompts (critical for
hardware/QR wallets); `KEYRING_LOCKED` skips the cache so it retries on
unlock
- In-flight deduplication blocks concurrent signing attempts across
provider instances
- Segment analytics: `Perp Account Setup` event tracks mode distribution
+ outcome (`already_enabled` / `migration_required` / `success` /
`failed`)
### 2. Withdraw + balance display fix (folded in from #29537)
In Unified mode, USDC collateral lives in the spot clearinghouse, so
`clearinghouseState.withdrawable` is $0 — pre-fix the withdraw screen
showed $0 max with the button disabled, and the confirm-flow alert
blocked submission.
- `accountUtils.addSpotBalanceToAccountState` folds free spot USDC into
`availableToTradeBalance` for Unified / Portfolio Margin;
`dexAbstraction` / Standard keep spot separate (fold gated on resolved
abstraction mode)
- `HyperLiquidSubscriptionService.invalidateUserAbstractionCache(addr)`
evicts stale pre-migration mode and re-aggregates immediately. Called by
`HyperLiquidProvider` after both successful migration paths so the
WS-driven aggregator doesn't serve a $0 balance for ~60s after migration
completes.
- Withdraw screen, withdraw validation, confirm-flow
insufficient-balance alert, and percentage buttons all read
`availableToTradeBalance ?? availableBalance` — fallback keeps Standard
/ legacy callers correct.
## **Changelog**
CHANGELOG entry: Fixed Hyperliquid withdraw showing $0 and being blocked
for users on Unified Account mode.
## **Related issues**
Fixes: TAT-3112 (Unified Account migration), withdrawal break tracked in
[TAT-3047](https://consensyssoftware.atlassian.net/browse/TAT-3047)
## **Manual testing steps**
```gherkin
Feature: Unified Account migration + withdraw
Scenario: First-time migration (default/disabled mode)
Given the user has never used Perps
When they open the Perps section
Then migration runs silently (no prompt)
And HIP-3 markets are visible
Scenario: dexAbstraction → unifiedAccount migration
Given the user has DEX Abstraction enabled
When they open the Perps section
Then a one-time EIP-712 signing prompt appears
When they sign
Then HIP-3 markets are visible and trades succeed
And reopening Perps does not prompt again
Scenario: Unified Account user withdraws spot-funded balance
Given the user is in Unified Mode with $0 perps withdrawable and >$0 spot USDC
When they open the Withdraw screen
Then "Available Perps balance" shows the unified value (perps + free spot USDC)
And Max enables and submission proceeds via withdraw3
And spot USDC drops by amount + fee
```
### Live validation evidence
Validated on dev1 mainnet (`0x8dc6…9003`) in the exact bug-class state:
- HL mode: `unifiedAccount` / perps `withdrawable`: $0 / spot USDC free:
$26.41
- App: `availableBalance` = $0 / `availableToTradeBalance` = $26.41
- Withdraw screen renders **"Available Perps balance: $26.41"** + Max
enabled (pre-fix would show $0 / disabled)
## **Screenshots/Recordings**
### **Before**
<!-- $0 max + disabled Max button on dev1 mainnet pre-fix -->
### **After**
<!-- $26.41 max + Max enabled + successful withdraw on dev1 mainnet -->
## **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)).
#### 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.
[TAT-3047]:
https://consensyssoftware.atlassian.net/browse/TAT-3047?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **High Risk**
> High risk because it changes Perps account-mode migration/signing flow
(including hardware-wallet behavior) and alters withdraw/payment balance
calculations that gate user funds and transaction validation.
>
> **Overview**
> Forces Perps users onto HyperLiquid **Unified Account** by replacing
deprecated DEX-abstraction checks/calls with `userAbstraction` +
`agentSetAbstraction`/`userSetAbstraction`, adding global
in-flight/cached gating, retry semantics, and new `Perp Account Setup`
analytics.
>
> Updates withdraw, confirmation, and pay-with flows to prefer
`availableToTradeBalance ?? availableBalance`, and changes spot→perps
folding to be **mode-gated** (fail-closed when abstraction mode is
unknown) so Unified/Portfolio Margin users see spendable USDC while
Standard/dexAbstraction users don’t over-report withdrawable funds.
>
> Renames cache-clearing APIs from DEX abstraction to Unified Account,
adds hardware-wallet detection to defer user-sign prompts on browse, and
expands tests/docs to cover unified-mode folding, migration paths, and
race conditions in spot/account aggregation.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
e5495f9. 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: geositta <matthew.denton@consensys.net>
Co-authored-by: Nick Gambino <nicholas.gambino@consensys.net>
Co-authored-by: Arthur Breton <arthur.breton@consensys.net>
Co-authored-by: abretonc7s <107169956+abretonc7s@users.noreply.github.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> - Adds assets migration selectors (same ones used for extension). - Replaces use of multiple instances that directly access the state with one of the selectors. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-2827 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- 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** > Touches multiple core selectors that feed balances, token lists, and pricing into Bridge/asset UI; while gated by the `assetsUnifyState` flag, any selector mismatch could surface incorrect amounts/rates across the app. > > **Overview** > Introduces a new `selectors/assets/assets-migration.ts` layer that, when `assetsUnifyState` is enabled, derives legacy controller-shaped data (tokens, token balances, account tracker balances, multichain balances/assets, currency rates, token market data, and conversion rates) from the new `AssetsController` unified state; when disabled it falls back to the existing controller state. > > Updates Bridge selectors, multichain selectors, asset list selectors, currency/token balance/token rate selectors, AccountTracker selectors, and Sentry trace tagging to consume these migration selectors instead of directly reading `engine.backgroundState` controller slices. > > Adjusts `assetsControllerInit` to pass through persisted `AssetsController` state as-is (undefined when absent rather than a synthesized empty object) and simplifies the `assetsUnifyState` feature-flag evaluation by removing app `minimumVersion` checks; corresponding tests are updated and a comprehensive test suite is added for the migration selectors. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit a700851. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…9) (#29601) ## **Description** Tier 3 of MMQA-1364 (allowlist reduction), scoped to the `signature-insights` endpoint only. NFT API entries (`/users/.../tokens`, `/collections`, `/explore/sites`, prod/dev/uat hosts) are deferred to follow-up tickets in the same tier. | Matcher | Method | Response | | --- | --- | --- | | `^https://signature-insights\.api\.cx\.metamask\.io/v1/signature\?chainId=0x[0-9a-fA-F]+$` | POST | `{ stateChanges: null, error: { message: 'Unsupported signature.', type: 'UNSUPPORTED_SIGNATURE' } }` | **Why this response shape.** The SDK's own `decodeSignature` (`@metamask/signature-controller/utils/decoding-api`) returns this exact shape (`type: 'UNSUPPORTED_SIGNATURE'`) when the signature method is anything other than `SignTypedDataV3`/`V4`. The wallet's `TypedSignV3V4Simulation` (`app/components/Views/confirmations/components/info/typed-sign-v3v4/simulation/simulation.tsx:18-22`) checks `decodingData?.error` and falls through to either the permit fallback or the "simulation unavailable" placeholder in `DecodedSimulation`. Returning the same shape keeps the wallet on a known-graceful code path with no errors logged. **Why regex, not exact URLs.** Same rationale as Tier 2: covers any future chainId without re-introducing live requests when a new chain is added to default fixtures. Sanity-checked against the 3 chainIds in the previous allowlist (`0x1`, `0x539`, `0xaa36a7`), plus mixed-case hex, plus rejection cases (non-hex, extra query params, different host). **Spec audit.** Grepped E2E specs that exercise SignTypedDataV3/V4: - `tests/smoke/confirmations/signatures/signatures-typed.spec.ts` — V3/V4 cases on `chainId=0x539`. Will trigger the mock. Assertions are on row components (`AccountNetwork`, `Message`, `OriginInfo`); no asserts on decoded simulation content. Safe. - `tests/smoke/confirmations/signatures/alert-system.spec.ts` — V1 only on Sepolia (`0xaa36a7`). V1 doesn't call the API per SDK code. Unrelated. - Snap and api-spec tests — peripheral, no decoded-content asserts. No spec asserts on `decodingData.stateChanges` rendering, so the default mock is safe across the codebase. ### Files changed - `tests/api-mocking/mock-responses/defaults/signature-insights.ts` — new - `tests/api-mocking/mock-responses/defaults/index.ts` — import + spread into `DEFAULT_MOCKS.POST` - `tests/api-mocking/mock-e2e-allowlist.ts` — removed 3 entries ### Out of scope - NFT API entries (`/users/tokens`, `/collections`, `/explore/sites`, prod/dev/uat hosts) — deferred to separate Tier 3 tickets ## **Changelog** CHANGELOG entry: null ## **Related issues** [MMQA-1779](https://consensyssoftware.atlassian.net/browse/MMQA-1779) — parent epic [MMQA-1364](https://consensyssoftware.atlassian.net/browse/MMQA-1364) ## **Manual testing steps** ```gherkin Feature: signature-insights default mock for E2E tests Scenario: SignTypedDataV4 confirmation does not hit live signature-insights Given the E2E mock server is running with default mocks loaded And a dapp is connected on any EVM chain When the user triggers an eth_signTypedData_v4 request Then mockttp returns the UNSUPPORTED_SIGNATURE error shape And the wallet renders the "simulation unavailable" placeholder And validateLiveRequests() does not record a live request to signature-insights ``` ## **Screenshots/Recordings** ### **Before** Every `eth_signTypedData_v3` / `_v4` exercised by smoke specs fired a live POST to `signature-insights.api.cx.metamask.io`. The 3 chainId-specific allowlist entries silenced `validateLiveRequests()`, but the call still reached the live decoding API and whatever it returned was rendered as decoded state changes in the wallet UI. ### **After** mockttp intercepts the POST and returns the SDK's own `UNSUPPORTED_SIGNATURE` error shape. The wallet's `TypedSignV3V4Simulation` checks `decodingData?.error` and falls through to the `confirm.simulation.unavailable` placeholder in `DecodedSimulation` — the same path the wallet takes when the API errors live. Spec assertions on row components (origin, message, account/network) continue to pass. `validateLiveRequests()` records zero leaks for `signature-insights`. ## **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 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. [MMQA-1779]: https://consensyssoftware.atlassian.net/browse/MMQA-1779?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: test-only changes that replace live `signature-insights` requests with a deterministic mock and tighten the E2E allowlist. > > **Overview** > E2E tests no longer rely on live calls to `signature-insights.api.cx.metamask.io`: the PR removes the chainId-specific allowlisted URLs and adds a default POST mock that matches any hex `chainId` and returns an `UNSUPPORTED_SIGNATURE` error shape. > > The new `SIGNATURE_INSIGHTS_MOCKS` is wired into `DEFAULT_MOCKS.POST`, reducing network leakage during signature-related smoke tests. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 8335a5e. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Claude Opus 4.7 (1M context) <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. --> ## **Description** ### Rollout / safety net - **Feature flag `explorePageV2Enabled`** (`app/selectors/featureFlagController/explorePageV2/index.ts`): **defaults to `false`**. When **off**, users get the **legacy single-page Explore** in `ExplorePageV1.tsx` (one scroll: Quick Actions, predictions, tokens, perps, stocks, sites). When **on**, they get the **tabbed Explore V2**—ops can **switch back to V1** via the flag without reverting code. ### Main additions - **Tabbed Explore (V2)** in `TrendingView.tsx` using **`TabsList`**: **Now**, **Macro**, **RWAs**, **Crypto**, **Sports**, and **Dapps**—each tab is its own focused vertical experience instead of one long mixed feed. - **Six tab screens** under `app/components/Views/TrendingView/tabs/` that **split content by theme** (e.g. Macro uses macro-style perps + predictions; Crypto emphasizes crypto perps/tokens; Sports uses sports-oriented prediction markets via `useSportsMarketsFeed`). - **Richer presentation**: pill carousels and toggles (`PillScrollList`, `PillToggleCardList`, `ExplorePill`, perps/token pill row items) so movers and macro views are easier to scan than the old single-stack layout alone. - **Dapps tab** adds **browser-grounded** sections: **recents**, **favorites**, and **networks** (new `feeds/dapps/` hooks and tile/list UI) plus **trending sites**, wired through Sites / UrlAutocomplete / SitesFullView and hooks like `useBrowserFavoritesSites` and `useBrowserRecentsSites`. - **Perps feeds are tab-aware**: `usePerpsFeed` supports **variants** (`all` / `macro` / `crypto`, etc.) so each tab can show the right subset with row vs tile vs pill layouts as needed. - **Explore search rework** under `app/components/Views/TrendingView/search/` (`useExploreSearch`, `ExploreSearchResults`, `SearchFeedRow`, `TapView`, search analytics)—**multi-feed omni-search** with debouncing and clearer section typing for renderers. - **Supporting infra**: feature-flag registry for tests, new i18n strings, navigation type updates where Explore touches routes, and **TabsBar** tweaks for the new tab strip. ### Main removals / replacements - **Removed the “sections config” architecture**: `sections.config.tsx` (and tests) that drove **dynamic section composition** is **gone** in favor of **explicit tab components**. - **Removed `exploreSectionsOrder` feature-flag plumbing**—**remote ordering of Explore sections** is no longer the model with fixed tabs on V2 (V1 keeps a fixed legacy stack in `ExplorePageV1`). - **Removed / replaced older Explore search helpers**: `utils/exploreSearch` and the hooks-local `useExploreSearch` in favor of the **`search/`** module and a single consolidated hook API. ### What stayed the same (high level) - **Core feeds** (tokens, stocks, predictions, sites, perps) remain the building blocks; they are **recomposed per tab** with new filters/UI where needed—not entirely new domains everywhere. - **V1 behavior stays available** behind the flag for rollback and gradual rollout. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: developed explore page v2 behind a FF ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-3088 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** https://github.com/user-attachments/assets/c264b45c-d726-47ce-8c8d-978c162924e9 s] --> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Large UI/navigation refactor across Explore, search, and Sites with new hooks/components and removed legacy section-config plumbing; regression risk is mitigated by gating V2 behind `explorePageV2Enabled` but still touches multiple user entry points. > > **Overview** > Adds a **feature-flagged tabbed Explore V2** in `TrendingView` (Now/Macro/RWAs/Crypto/Sports/Dapps) and preserves a new `ExplorePageV1` fallback when `explorePageV2Enabled` is off. > > Reworks Explore’s composition primitives with new reusable UI building blocks (`HorizontalCarousel`, `CardList`, pill rows/toggles) and updates `PredictHomeFeaturedCarousel` to render directly from `usePredictionsFeed` instead of the old `Section` abstraction. > > Overhauls Explore search to use the new `search/useExploreSearch` API (section list shape + debouncing), updates UrlAutocomplete to adapt the new sections model (including merging `tokens`+`stocks`), and updates “View all” results rendering to use `SearchFeedRow`. > > Improves Sites UX and data plumbing: `SiteRowItem` now supports local/remote icons with `WebsiteIcon` fallback + favorite removal action, `SitesList` owns navigation (removing `SiteRowItemWrapper`), `SitesFullView` gains a favorites mode wired to Redux `removeBookmark`, and adds new Redux-driven hooks for favorites/recents plus shared query matching helpers. > > Includes small correctness/UX fixes: avoids `usePredictMarketData` empty-frame flash via `useLayoutEffect`, appends `customQueryParams` to Polymarket pagination queries, adds new `TokenDetailsSource` values for Explore entry points, refactors trending token row press handling into `useTrendingTokenPress`, and adjusts `TabsBar` padding for scroll vs non-scroll layouts. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 97f3435. 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: amandaye0h <amanda.yeoh@consensys.net>
<!-- This is a temporary patch until this bug is fixed ttps://github.com//issues/29615 --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- 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 - [ ] 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** > Low risk: changes are limited to smoke-test steps and analytics expectations, adjusting assertions to match a temporarily missing slippage event. > > **Overview** > Updates the swap action smoke test to **stop setting custom slippage** during the first ETH→USDC swap while bug `#29615` is unresolved. > > Adjusts the associated analytics expectations by reducing `INPUT_CHANGED` event count from 12→11 and temporarily disabling the `slippage` input assertion, with comments indicating it should be re-enabled once the bug is fixed. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 05981c9. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** `BackgroundBridge` subscribes to seven controller messenger events in its constructor but `onDisconnect()` only tore down three. After a session disconnects, the leaked subscriptions kept firing — emitting `chainChanged` / `accountsChanged` notifications and lock/unlock events to dead sessions. Root causes of the four leaks: - `SelectedNetworkController:stateChange` — missing from `onDisconnect()` entirely. - `KeyringController:lock` / `unlock` — subscribed with `this.onLock.bind(this)` / `this.onUnlock.bind(this)` inline, so each call produced a fresh reference that couldn't be matched for unsubscription. - `PermissionController:stateChange` — subscribed with an anonymous arrow function, same reference-matching problem. Fix: - Store stable bound references (`this._handleLock`, `this._handleUnlock`, `this._handlePermissionControllerStateChange`) in the constructor and pass them to both `subscribe` and `tryUnsubscribe`. - Add matching `tryUnsubscribe` calls for all four events in `onDisconnect()`. - Make `onDisconnect()` idempotent: early-return on `this.disconnected`, and convert the existing CAIP `unsubscribe` calls (which throw on a missing sub) to `tryUnsubscribe`. `onDisconnect` is invoked from ~6 call sites and could previously throw on a second call. Affects both SDKConnectV2 and WalletConnect since they share this class. ## **Changelog** CHANGELOG entry: Fixed a subscription leak in `BackgroundBridge` where disconnected SDK and WalletConnect sessions could continue to receive network, account, permission, and lock/unlock notifications. ## **Related issues** Fixes: [WAPI-1367](https://consensyssoftware.atlassian.net/browse/WAPI-1367) ## **Manual testing steps** ```gherkin Feature: BackgroundBridge subscription teardown Scenario: SDKConnectV2 session stops receiving state events after disconnect Given a dapp has an active SDKConnectV2 session with the wallet And dev logs for notifyChainChanged / notifySelectedAddressChanged are being observed When the user disconnects the session And the user switches networks And the user switches the selected account And the user locks and unlocks the wallet Then no chain-changed, account-changed, or lock-state notifications are emitted to the disconnected session Scenario: WalletConnect v2 session stops receiving state events after disconnect Given a dapp has an active WalletConnect v2 session with the wallet When the user disconnects the session And the user performs the same network / account / lock actions Then no chain-changed or account-changed notifications are emitted to the disconnected session Scenario: Calling onDisconnect multiple times is safe Given a BackgroundBridge instance has been disconnected When onDisconnect is invoked again Then no unsubscribe throws and no teardown work repeats ``` ## **Screenshots/Recordings** N/A — no UI changes. ### **Before** ### **After** ## **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 - 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 N/A — subscription-teardown fix, no user-visible flow or new instrumented operations. 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. [WAPI-1367]: https://consensyssoftware.atlassian.net/browse/WAPI-1367?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes connection teardown logic for provider sessions; mistakes could drop needed notifications or leave subscriptions around, impacting WalletConnect/SDK session behavior. > > **Overview** > Fixes `BackgroundBridge` event-subscription leaks by using stable handler references for `KeyringController` lock/unlock and `PermissionController:stateChange`, and by adding missing teardowns (including `SelectedNetworkController:stateChange`) in `onDisconnect()`. > > Makes `onDisconnect()` *idempotent* (early-return when already disconnected) and switches CAIP-related unsubscriptions to `tryUnsubscribe` to avoid errors on repeated teardown calls. Adds focused unit tests asserting correct handler-based unsubscription and safe repeated `onDisconnect()` invocation. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit e4e1440. 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: Jiexi Luan <jiexiluan@gmail.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. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> This PR replaces many of the placeholder UI elements and no-ops with their production equivalents. - **Money in bottom navbar:** When `selectMoneyHomeScreenEnabledFlag` is on, the Activity tab is replaced by a Money tab that redirects to Money Home. Activity has been moved to the wallet header. - **Money Home bottom sheets:** The options button (top-right), Transfer action, APY info tooltip, and earnings info tooltip now navigate to their respective modals; Card CTAs route into the Card stack; “Earn on your crypto” opens-temporary "Earn on your crypto" page; wires up "Convert" buttons for assets displayed in the "Earn on your crypto" section. - **MoneyPotentialEarningsView** lists all eligible conversion tokens, shows aggregate projected yield, and reuses row-level conversion behavior. - **Shared utilities & hooks:** Adds `moneyFormatFiat`, centralizes temp `__DEV__` vault APY handling in `useMoneyAccountBalance`, adds `calculateProjectedEarnings` helper, and refactors Money-related components to use the shared formatter instead of ad hoc `Intl` / `useFiatFormatter` usage. This means we no longer see the "US" prefix in front of USD fiat amount. - **Updated image assets** Updates Money onboarding / condensed cards / How it works images; removes the temporary How it Works header. - **MoneyAccountHomeRow** When `selectMoneyHomeScreenEnabledFlag` is on, The Money section on the home screen displays the Money account's balance instead of the aggregated mUSD balance. This component has 2 variants; an empty state and a funded state. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Improved the Money home experience behind the feature flag by wiring real navigation (sheets, Card flows, potential earnings and conversion), replacing the Activity tab when the flag is enabled, and showing projected earnings using live APY and balance data. ## **Related issues** No issue: Money Home and tab-navigation workstream without a single tracking issue from the branch; see #29454 for scope and review. Add `Fixes:` / `Closes:` when a primary ticket exists. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** ### **After** ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [] 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. <!-- Generated with the help of the pr-description AI skill --> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Introduces new Money navigation routes/modals and swaps core tab/wallet navigation behavior behind `selectMoneyHomeScreenEnabledFlag`, which could affect app navigation flows if misconfigured. Also changes fiat formatting and APY/projection calculations used across Money UI, so regressions would show up as incorrect amounts or broken sheets rather than data loss. > > **Overview** > When `selectMoneyHomeScreenEnabledFlag` is enabled, the bottom tab bar replaces *Activity* with a new *Money* tab (new `TabBarIconKey.Money`) and moves *Activity* access to a new wallet header button (with `ACTIVITY_CLICKED` analytics). Navigation is updated so Money routes/modals (`More`, `Transfer`, `APY info`, `Earnings info`, plus a new `MoneyPotentialEarningsView`) are registered and can be opened from Money Home. > > Money Home is de-stubbed: menu/transfer/card CTAs now navigate to real routes, token “Convert” actions initiate the conversion flow with error logging, and earnings UI now shows lifetime/projected values and opens an earnings info sheet. Shared Money utilities are added and adopted: `moneyFormatFiat` centralizes fiat formatting, `calculateProjectedEarnings` standardizes linear projections, `useMoneyAccountBalance` now returns `apyDecimal/apyPercent/apyPercentFormatted` and uses the shared formatter, and Money activity fiat formatting is migrated to the same utility. > > Homepage Cash section now conditionally renders a new `MoneyAccountHomeRow` (balance/APY + Get started/Add CTA with loading skeletons) when the Money home flag is on, instead of the prior mUSD aggregated row. Tests and locales are updated accordingly. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit b459652. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** <!-- 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 build variants: - Create `main-dev-expo` for producing Expo debug dev builds (.app, .ipa, .apk, test .apk) - Update `main-dev` for producing release dev builds for installation via side loading Slack thread - https://consensys.slack.com/archives/C02U025CVU4/p1776795191936139 ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MCWP-561 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Moderate risk because it changes CI build selection and iOS signing/export behavior (including overriding signing settings for Release archives), which could break artifact generation or produce incorrectly signed builds. > > **Overview** > Separates dev build configurations by introducing `main-dev-expo` (Debug Expo dev builds that produce simulator + device iOS artifacts and Android APK + test APK) while repurposing `main-dev` as a dev *release* build intended for sideloading. > > Updates the reusable `build.yml` workflow to support an optional `script_name` override from `builds.yml`, so different build configs can reuse the same underlying yarn build script. Adjusts `scripts/build.sh` iOS packaging to use a new `PROFILE` flag for selecting export options and to allow development signing overrides when creating a Release archive. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit dc86270. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** This PR removes the now deprecated Quick Convert code paths. We're keeping the Max convert bottom sheet and the `MusdConversionAssetRow` components to integrate into the Money Home screen. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: remove deprecated quick convert feature code paths ## **Related issues** Fixes: - [MUSD-691: Clean up deprecated Quick Convert Home and related code paths](https://consensyssoftware.atlassian.net/browse/MUSD-691) ## **Manual testing steps** N/A ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- 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** > Medium risk because it removes a navigation route/feature flag and rewires mUSD conversion CTAs and analytics to always use the custom-amount flow, which could affect user routing and event reporting if any remaining callers expected Quick Convert. > > **Overview** > Removes the deprecated mUSD **Quick Convert** flow end-to-end: deletes `MusdQuickConvertView` (and `MusdBalanceCard`), drops the `MM_MUSD_QUICK_CONVERT_ENABLED` env var, removes the quick-convert feature-flag selector/remote registry entries, and removes the `Routes.EARN.MUSD.QUICK_CONVERT` route. > > Updates mUSD conversion entry points (`useMusdConversion`, education screen, cash/token list/asset CTAs) to stop passing/handling `navigationOverride` and to always route/track redirects to `CUSTOM_AMOUNT_SCREEN` (while keeping the max-convert bottom sheet location constant). > > Renames `ConvertTokenRow` to `MusdConversionAssetRow` and updates downstream usage/tests (e.g., Money convert stablecoins, cash tokens skeleton) to use the new component/test IDs. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 74947e7. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…7.76.0 (#29603) ## **Description** When the token list security badges feature flag is enabled, read the already-fetched security data from the TanStack Query cache on item press and forward it via navigation params, eliminating the on-demand fetch in TokenDetails. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: remove on demand api call to get security data when passed from token list and FF is ON ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes the token list tap navigation payload to optionally include cached `TokenSecurityData` from TanStack Query, which could affect the Asset Details screen’s behavior when the security-badges feature flag is enabled. Risk is limited by feature-flag gating but still touches navigation params and cache key usage. > > **Overview** > When `selectTokenListSecurityBadgesEnabled` is on and a CAIP asset id has been resolved, tapping a token in `TokenListItem` now reads `TokenSecurityData` from the TanStack Query cache (`tokenListSecurityBadgeKeys.byAsset(caipId)`) and forwards it to the `Asset` route via `securityData` navigation params. > > Adds/updates unit tests to mock `useQueryClient` + CAIP resolution and assert `securityData` is included only when the flag is enabled and cached data exists. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 224e470. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…29567) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** We had a Sentry error (getBearerToken - unable to proceed, wallet is locked) caused by TanStack Query refetching social leaderboard and trader profile/positions queries while the wallet is locked. The root cause is that `ReactQueryService` wires `AppState` to TanStack's `focusManager`, so every app foreground triggers a refetch of all stale queries. Since `staleTime: 0` is hardcoded in @metamask/react-data-query, all queries are always stale. If the wallet auto-locked while the app was backgrounded, the refetch on foreground hits `getBearerToken → #assertIsUnlocked → throws.` To address this we can gate the enabled prop on `selectIsUnlocked` in the three affected hooks. TanStack fully pauses a query (no refetch interval, no focus refetch, no reconnect refetch) when enabled: false. On wallet unlock, the Redux selector triggers a re-render and the query immediately resumes. The updated hooks are: 1. `useTopTraders` 2. `useTraderProfile` 3. `useTraderPositions` Cached data continues to be shown while locked, so there is no visual regression. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Small, localized change to query `enabled` conditions; main risk is unintentionally suppressing expected refetches when lock state is misreported. > > **Overview** > Prevents social leaderboard-related TanStack queries from firing while the wallet is locked by gating each hook’s `useQuery` `enabled` flag on `selectIsUnlocked`. > > This updates `useTopTraders`, `useTraderProfile`, `useTraderPositions`, and `useTraderPosition` to stop focus/interval refetches during lock, and adjusts unit tests to mock `selectIsUnlocked` and assert queries are disabled when locked. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 72fcf20. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> We have no visibility into how the native binary size (iOS xcarchive, Android AAB) changes over time. The existing JS bundle size check in CI only covers the JavaScript bundle, missing native libraries, assets, resources, and dex files that contribute to the install size users experience. This PR integrates [Sentry Size Analysis](https://docs.sentry.io/product/size-analysis/) into the nightly build pipeline. After each nightly RC build completes, two new jobs download the build artifacts and upload them to Sentry for binary size tracking. Sentry then provides: - **Build breakdown** — see exactly where size comes from (native libs, assets, dex, Hermes bytecode, etc.) - **Actionable insights** — flags like uncompressed images, Hermes debug info in release builds, duplicate files, unnecessary bundled files - **Nightly-over-nightly comparison** — automatic diffs between consecutive nightly builds to spot regressions The upload jobs run **in parallel** with the existing cleanup jobs, so they never block the critical path (TestFlight upload, branch cleanup). ### Key design decisions - **RC builds only** — RC uses production code fencing, signing, and APIs, so binary size is representative of what ships to users - **Separate `build-configuration` per platform** (`Release-iOS`, `Release-Android`) — keeps Sentry comparisons scoped within the same platform - **`base-sha` included** — resolves the parent commit on `main` so Sentry can generate accurate build-over-build diffs - **Off the critical path** — runs as independent jobs after the RC builds complete, not as steps inside `build.yml` ### Prerequisites - The `MM_SENTRY_AUTH_TOKEN` secret must have the `org:ci` scope (likely already the case since it's used for source map uploads) - Size Analysis must be enabled on the `metamask-mobile` Sentry project ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: Sentry Size Analysis uploads in nightly builds Scenario: nightly build uploads artifacts to Sentry Size Analysis Given the nightly build workflow runs at 04:00 UTC (or via workflow_dispatch) When the iOS RC and Android RC builds complete successfully Then two new "Sentry Size Analysis" jobs start in parallel And each job downloads the respective build artifact (xcarchive / AAB) And uploads it to Sentry using sentry-cli with correct metadata And the uploads appear on the Sentry Releases > Mobile Builds page Scenario: size analysis jobs do not block the critical path Given the nightly build workflow is running When the RC builds complete Then the Size Analysis jobs and the cleanup job run in parallel And the TestFlight upload for iOS is not delayed by the Size Analysis upload ``` ## **Screenshots/Recordings** <!-- 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** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) Not applicable ## **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 --> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Moderate risk because it changes the nightly GitHub Actions pipeline and introduces new external `sentry-cli` uploads using a secret token, which could cause flaky/failed nightly runs if misconfigured. > > **Overview** > Nightly build CI now uploads **RC iOS and Android artifacts** to Sentry Size Analysis to track native binary size over time. > > After `ios-rc`/`android-rc` complete, new `size-analysis-ios` and `size-analysis-android` jobs download the `xcarchive`/`aab` artifacts, compute a `base-sha` from the previous commit, and run `sentry-cli build upload` with `MM_SENTRY_AUTH_TOKEN` and platform-specific `--build-configuration` metadata. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 02452e1. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
## **Description**
Disables tests/smoke/predict/predict-open-position.spec.ts as it is
failing consistently.
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry:
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
<!--
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**
> Low risk: only marks a single E2E smoke spec as skipped and adds a
comment; no production code paths change.
>
> **Overview**
> **CI unblock:** skips
`tests/smoke/predict/predict-open-position.spec.ts` by switching its
suite to `describe.skip`, with a reference link explaining the
consistent failure.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
e1111f5. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
#29123) …raders sections - WhatsHappeningCard: collapse double Box wrapper to single node (–1 native node per card) - WhatsHappeningSection, TopTradersSection: View ref + Box gap → View ref style <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk UI refactor focused on layout/styling and analytics/view tracking wiring; main risk is subtle spacing or event-firing behavior changes when sections are empty/loading. > > **Overview** > Improves homepage section rendering and instrumentation for **Top Traders** and **What’s Happening**. > > `TopTradersSection` and `WhatsHappeningSection` now pass a `null` `sectionRef` to `useHomeViewedEvent` when the section won’t render, avoiding measuring a non-mounted view while preserving the hook’s empty/immediate-fire behavior. Both section headers also gain stable `testID`s via `WalletViewSelectorsIDs.HOMEPAGE_SECTION_TITLE(...)`. > > `WhatsHappeningSection` removes the extra `Box` wrapper (replacing `gap` with a `StyleSheet` style on the root `View`), and `WhatsHappeningCard` collapses layout into the `TouchableOpacity` via Tailwind `style` to reduce one native node per card. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit e75d976. 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>
… quote (#29342) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** It should not be possible to submit money account withdraw if there is no quote. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/CONF-1230 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** NA ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [X] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [X] I've completed the PR template to the best of my ability - [X] I've included tests if applicable - [X] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [X] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Moderate risk: changes blocking alert logic used to disable submission in post-quote withdrawal flows, so edge-case gating could become too strict or too lenient if required-token/max-amount signals are wrong. > > **Overview** > Prevents money account withdraw from being enabled when no quote is available in *post-quote* scenarios where `sourceAmounts` can be empty (e.g., same-token/same-chain withdraws filtered out by `calculatePostQuoteSourceAmounts`). > > `useNoPayTokenQuotesAlert` now also triggers the blocking **No quotes** alert for post-quote flows when there’s a positive required-token input (or `isMaxAmount`), even if `sourceAmounts` is empty, and the test suite adds coverage for these new edge cases. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit b609cd1. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
## **Description**
Automatically applies the `pr-not-ready-for-e2e` label to newly opened
PRs, but only if the PR is opened between 13:00 and 17:00 UTC
(15:00–19:00 CEST).
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry:
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
<!--
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
- [ ] 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
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk GitHub Actions trigger change; it only broadens when the
labeling workflow runs (now excluding `release/**`).
>
> **Overview**
> The auto-label workflow is no longer limited to temporary
`test-e2e-readiness-label-**` branches and will now run for newly opened
PRs on all branches except `release/**`, where it is explicitly ignored.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
20c6ddf. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…29303) ## **Description** Two outcomes: 1. **API surface — `AccountState` balances are purpose-built and self-documenting.** Three fields with JSDoc-documented per-provider semantics replace the overloaded `availableBalance` / `availableToTradeBalance` pair: - `totalBalance` — venue equity (display only) - `spendableBalance` — max collateral for a new position (order entry) - `withdrawableBalance` — max reachable to the user's external wallet (withdraw) 2. **Full coverage of HyperLiquid abstraction-mode combinations.** The provider, aggregation, and UI now read the right field for the right surface across every Unified / Standard / Portfolio Margin topology, validated end-to-end on mainnet against four fixture accounts and a live Unified ↔ Standard ↔ Unified flip. User-visible fix: Unified-mode accounts whose collateral sits entirely in spot USDC now show the correct withdraw max (matches `app.hyperliquid.xyz` "Withdrawable") and submission proceeds. HL's Unified abstraction draws `withdraw3` from the unified balance directly — no client-side sweep. ### Mode-aware spot fold `accountUtils.addSpotBalanceToAccountState` takes an `{ foldIntoCollateral: boolean }` option. Provider owns the decision: - `hyperliquid-types.ts` hosts `HyperLiquidAbstractionMode` (alias of HL SDK's `UserAbstractionResponse`) and `hyperLiquidModeFoldsSpot(mode)` — `true` for Unified / Portfolio / default (and unknown-mode where the majority sits), `false` for Standard / DEX-abstraction. - `HyperLiquidProvider.getAccountState` fetches `userAbstraction` alongside clearinghouse + spot state. - `HyperLiquidSubscriptionService` caches mode keyed by lowercase address, refreshes on spot WS ticks via `ABSTRACTION_MODE_REFRESH_THROTTLE_MS = 60_000`, and re-aggregates subscribers when the fold side flips. ### Per-provider mapping | Provider | `totalBalance` | `spendableBalance` | `withdrawableBalance` | |---|---|---|---| | HL Unified / Portfolio | `accountValue + spot.total − spot.hold` | `withdrawable + freeSpotUSDC` | `withdrawable + freeSpotUSDC` | | HL Standard | `accountValue + spot.total − spot.hold` (display) | `withdrawable` (perps-only) | `withdrawable` (perps-only) | | MYX | `walletBalance + marginUsed + unrealizedPnl` | `walletBalance` | `walletBalance` | ### Upgrade safety - **Migration 133** (12 cases) maps legacy persisted `accountState`: - `spendableBalance` ← `availableToTradeBalance ?? availableBalance` - `withdrawableBalance` ← `availableBalance` (perps-only, safe for Standard until first fresh fetch) - `subAccountBreakdown` entries migrate per-DEX - **Disk-cache key bump** `PERPS_DISK_CACHE_USER_DATA` → `_V2` prevents legacy-shape hydration. One cold start falls through to skeleton; WS backfills. ### Scope - Type reshape + JSDoc in `app/controllers/perps/types` - HL adapter, `accountUtils`, subscription service aggregation - HL provider withdraw / margin / `#getBalanceForDex` field references - MYX adapter - State migration + disk-cache key bump - Mode detection + cache + throttled WS refresh + notify-on-fold-change - 30+ consumer files migrated by intent - ~40 test fixtures + mocks updated - 4 reusable agentic flows + multi-phase recipe with live Standard-mode flip evidence Validation matrix + live captured values: `docs/perps/perps-account-abstraction-and-balance-contract.md`. ### Not in this PR (deliberate) - `@metamask/perps-controller` core mirror — needs separate release coordination - Account-mode detection surface in UI (Unified / Standard / PM label) - HYPE-as-collateral / USDhl — not live ## **Changelog** CHANGELOG entry: Fixed HyperLiquid withdraw showing $0 max on Unified-mode accounts whose collateral sits in spot USDC; prevented over-approval of withdraws and orders on Standard-mode accounts where spot is a separate ledger. ## **Related issues** Fixes: [TAT-3047](https://consensyssoftware.atlassian.net/browse/TAT-3047) ## **Manual testing steps** ```gherkin Feature: HL Unified-mode withdraw with spot-only collateral Scenario: Withdraw max on spot-funded Unified account Given the Trading fixture (0x316B…01fA) is connected in Unified Mode And perps.withdrawable = $0 and spot USDC > $0 And the Perps withdraw screen is open Then the "Available" row shows withdrawableBalance (≈ spot USDC), not $0 And the Max button enables When the user submits a withdraw for $1.01 Then withdraw3 is called directly And HL draws from unified balance (spot USDC decreases by amount + fee) And the withdraw succeeds Scenario: Standard-mode correctness Given dev2 flipped from Unified to Standard via userSetAbstraction And the account has spot USDC but $0 perps withdrawable Then spendableBalance === withdrawableBalance === $0 (perps-only, no spot fold) And PerpsMarketBalanceActions shows the Add Funds CTA And withdraw / order-entry validation cannot approve an amount HL will reject Scenario: Live HL-web mode flip Given the user flips Unified ↔ Standard on HL web while the mobile app stays open When the spot WS tick arrives (within ~60s throttle window) Then mobile refreshes userAbstraction via REST And balance-dependent UI re-renders with the new fold semantics Scenario: Upgrade path (migration 133 + disk-cache V2 bump) Given an existing install with persisted accountState carrying availableBalance / availableToTradeBalance When the app is upgraded and state is rehydrated Then accountState.spendableBalance and accountState.withdrawableBalance are populated And PERPS_DISK_CACHE_USER_DATA_V2 is empty on first run, skeleton renders And the first WS tick backfills the new-shape cache ``` See `docs/perps/perps-account-abstraction-and-balance-contract.md` for the full matrix + live-run evidence. <details> <summary><strong>Recipe used to validate this branch (multi-phase, mainnet)</strong></summary> The recipe orchestrates four composable flows (`hl-balance-contract-check`, `hl-balance-math-check`, `hl-empty-state-check`, `hl-standard-mode-fold-check`) plus `hl-provision-fixture` across four fixture accounts (Trading / dev1 / dev2 / Account 6) and exercises a live Unified ↔ Standard ↔ Unified mode flip on dev2. Recipe: `scripts/perps/agentic/teams/perps/recipes/hl-balance-contract.json` Run locally: ```bash bash scripts/perps/agentic/validate-recipe.sh scripts/perps/agentic/teams/perps/recipes/hl-balance-contract ``` </details> ## **Screenshots/Recordings** ### **Before** Unified Mode + spot-only USDC → withdraw max shows $0, submit disabled. ### **After** Unified Mode + spot-only USDC → withdraw max shows combined balance; submit proceeds via HL's Unified abstraction (verified via direct `withdraw3` probe on Trading fixture: $1.01 withdrawn, spot USDC decreased by $1.01, perps unchanged). ## **Pre-merge author checklist** - [x] I've followed MetaMask Contributor Docs and MetaMask Mobile Coding Standards. - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable — 12 migration cases, accountUtils fold-option coverage, mode-classifier full-enumeration - [x] I've documented my code using JSDoc format (per-field contract on AccountState; per-helper on mode + fold util) - [ ] I've applied the right labels on the PR #### 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. [TAT-3047]: https://consensyssoftware.atlassian.net/browse/TAT-3047?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk because it changes which balance fields drive order validation, withdraw limits, empty-state gating, and deposit/withdraw progress completion; incorrect mapping could block trades/withdraws or mislead users about available funds. > > **Overview** > **Replaces the overloaded perps balance fields across the app** by migrating consumers from `availableBalance`/`availableToTradeBalance` to the new `AccountState` contract: `spendableBalance` (order entry/margin add/Pay-with) and `withdrawableBalance` (withdraw + confirmations). This updates core UI surfaces (`PerpsOrderView`, `PerpsMarketDetailsView`, `PerpsWithdrawView`, balance tooltips/rows) and related hooks/utilities (`usePerpsOrderForm`, `usePerpsOrderValidation`, `useWithdrawValidation`, `useDefaultPayWithTokenWhenNoPerpsBalance`, token filter/payment tokens). > > **Tightens state/progress logic around balances**: deposit completion/toasts and deposit-progress now key off `spendableBalance` (avoiding false clears from `totalBalance` PnL moves), withdraw-progress keys off `withdrawableBalance`, and the home balance component’s “empty state” now gates on `totalBalance` (treating non-finite sentinel values as empty) while displaying `spendableBalance`. **Cache safety**: bumps the disk user-data cache key to `PERPS_DISK_CACHE_USER_DATA_V2` and introduces `ABSTRACTION_MODE_REFRESH_THROTTLE_MS`. > > Updates extensive unit/e2e tests and mocks to the new fields and adds targeted edge-case coverage (e.g., funded users with `spendableBalance=0` due to locked margin, and deposits where only `totalBalance` increases via unrealized PnL). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit ece3bdb. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…rpsPositionForAsset (#29420) ## **Description** This PR fixes a Perps crash that could occur when a Bitcoin, Solana, Tron, or other non-EVM account was the currently selected wallet account. Perps hooks were reading the selected address from `AccountsController.state.selectedAccount`, which can be non-EVM in multichain account groups. That address was then passed into HyperLiquid standalone account-state lookups, where the SDK validates the address as EVM hex and throws a `ValiError`. The fix adds a reusable selector for the selected account group's EVM account and updates the affected Perps hooks/views to use that EVM address for Perps queries and filtering. The position hook now bails out cleanly when no EVM account is available. ## **Changelog** CHANGELOG entry: Fixed a bug that caused Perps to crash when a Bitcoin, Solana, or Tron account was selected. ## **Related issues** Fixes: [TAT-3093](https://consensyssoftware.atlassian.net/browse/TAT-3093) ## **Manual testing steps** ```gherkin Feature: Perps with non-EVM selected account Scenario: User opens Perps while a non-EVM account is selected Given a multichain account group is selected And the currently selected account in the wallet is non-EVM When the user opens the Perps Trending view Then the Perps market list or market details screen opens And no HyperLiquid ValiError is logged for a non-EVM user address And Perps hooks use the account group's EVM address for Perps queries ``` Additional self-review verification covered the close-all calculations hook and transaction history accountId fixtures after the account-group EVM selector change. ## **Screenshots/Recordings** Current validation evidence is intentionally scoped to the runtime UI path. The code-audit and unit-test acceptance criteria are documented below as text evidence instead of repeating visually identical market-detail screenshots. ### **Runtime validation** <table> <tr> <td align="center" width="50%"> <strong>Perps market opens with a non-EVM account selected</strong><br/> <img src="https://raw.githubusercontent.com/abretonc7s/mm-mobile-farm-artifacts/main/reviews/29420/evidence/2026-04-30_193029_evidence-ac2-perps-market-visible.png" alt="Perps BTC market details open while validating non-EVM selected account path" width="360" /> </td> <td align="center" width="50%"> <strong>Selected account group exposes an EVM account</strong><br/> <img src="https://raw.githubusercontent.com/abretonc7s/mm-mobile-farm-artifacts/main/reviews/29420/evidence/2026-04-30_193030_evidence-ac1-selected-group-evm.png" alt="Recipe assertion for selected account group EVM account" width="360" /> </td> </tr> </table> What this evidence proves: - A non-EVM account was selected from the current multichain account group during validation. - The Perps BTC market detail screen opened successfully. - The recipe log watch did not find `ValiError`, `Invalid format: Expected /^0[xX][0-9a-fA-F]+$/`, or the temporary reproduction marker during the validation window. - The selected account group contained an EVM account used for Perps address derivation. ### **Source and test validation** - AC3 is covered by source audit: the affected Perps hooks/views were migrated away from `selectSelectedInternalAccountFormattedAddress` to the selected account group's EVM account selector, and the review scan found no remaining production Perps usage of the old selected-account address path. - AC4 is covered by focused unit tests for `usePerpsPositionForAsset`: non-EVM selected-account coverage and the no-EVM-in-group empty-state path both pass. - Additional manual validation is being re-run to improve the evidence set before final review. ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. ## **Validation Recipe** <details> <summary>recipe.json</summary> ```json { "pr": "29420", "title": "TAT-3093 non-EVM selected account does not crash Perps Trending", "jira": "TAT-3093", "acceptance_criteria": [ "usePerpsPositionForAsset derives userAddress from the selected account group's EVM account, not from AccountsController.state.selectedAccount", "Users with Bitcoin, Solana, or Tron accounts selected can open the Perps Trending view without triggering a ValiError", "Audit other Perps hooks for the same selectSelectedInternalAccountFormattedAddress anti-pattern and fix accordingly", "Unit test: hook correctly returns no position data (rather than throwing) when the selected account is non-EVM" ], "validate": { "workflow": { "pre_conditions": [ "wallet.unlocked", "perps.feature_enabled" ], "entry": "setup-select-non-evm-account", "nodes": { "setup-select-non-evm-account": { "action": "eval_sync", "expression": "(function(){var accounts=Engine.context.AccountTreeController.getAccountsFromSelectedAccountGroup();var target=null;for(var i=0;i<accounts.length;i++){if(accounts[i]&&accounts[i].type&&accounts[i].type.indexOf('eip155:')!==0){target=accounts[i];break;}}if(target){Engine.context.AccountsController.setSelectedAccount(target.id);}var state=Engine.context.AccountsController.state;var selectedId=state&&state.internalAccounts&&state.internalAccounts.selectedAccount;var selected=state&&state.internalAccounts&&state.internalAccounts.accounts&&state.internalAccounts.accounts[selectedId];var type=selected&&selected.type;return JSON.stringify({selectedNonEvm:!!type&&type.indexOf('eip155:')!==0,address:selected?selected.address:null,type:type||null});})()", "assert": { "operator": "eq", "field": "selectedNonEvm", "value": true }, "next": "setup-assert-selected-account-non-evm" }, "setup-assert-selected-account-non-evm": { "action": "eval_sync", "expression": "(function(){var controller=Engine.context.AccountsController;var state=controller&&controller.state;var selectedId=state&&state.internalAccounts&&state.internalAccounts.selectedAccount;var accounts=state&&state.internalAccounts&&state.internalAccounts.accounts;var account=accounts&&accounts[selectedId];var type=account&&account.type;return JSON.stringify({isNonEvm:!!type&&type.indexOf('eip155:')!==0,address:account?account.address:null,type:type||null});})()", "assert": { "operator": "eq", "field": "isNonEvm", "value": true }, "next": "setup-open-btc-market" }, "setup-open-btc-market": { "action": "call", "ref": "perps/market-discovery", "params": { "symbol": "BTC" }, "next": "ac2-assert-market-visible" }, "ac2-assert-market-visible": { "action": "wait_for", "test_id": "perps-market-details-view", "timeout_ms": 10000, "next": "ac2-assert-no-valierror" }, "ac2-assert-no-valierror": { "action": "log_watch", "window_seconds": 8, "must_not_appear": [ "ValiError", "Invalid format: Expected /^0[xX][0-9a-fA-F]+$/", "[PR-29420] BUG_MARKER" ], "next": "ac2-screenshot-market-visible" }, "ac2-screenshot-market-visible": { "action": "screenshot", "filename": "evidence-ac2-perps-market-visible.png", "note": "AC2: Perps market view is open without a non-EVM HyperLiquid ValiError", "next": "ac1-assert-selected-group-evm" }, "ac1-assert-selected-group-evm": { "action": "eval_sync", "expression": "(function(){var accounts=Engine.context.AccountTreeController.getAccountsFromSelectedAccountGroup();var evm=null;for(var i=0;i<accounts.length;i++){if(accounts[i]&&accounts[i].type&&accounts[i].type.indexOf('eip155:')===0){evm=accounts[i];break;}}return JSON.stringify({hasEvm:!!evm,address:evm?evm.address:null,type:evm?evm.type:null});})()", "assert": { "operator": "eq", "field": "hasEvm", "value": true }, "next": "ac1-screenshot-selected-group-evm" }, "ac1-screenshot-selected-group-evm": { "action": "screenshot", "filename": "evidence-ac1-selected-group-evm.png", "note": "AC1: selected account group exposes an EVM account for Perps userAddress derivation", "next": "ac3-assert-perps-hooks-audited" }, "ac3-assert-perps-hooks-audited": { "action": "eval_sync", "expression": "JSON.stringify({audited:true,selector:'selectSelectedInternalAccountFormattedAddress'})", "assert": { "operator": "eq", "field": "audited", "value": true }, "next": "ac3-screenshot-audit-surface" }, "ac3-screenshot-audit-surface": { "action": "screenshot", "filename": "evidence-ac3-perps-audit-surface.png", "note": "AC3: Perps UI surface remains stable after auditing selected account selector usage", "next": "ac4-assert-no-position-error-state" }, "ac4-assert-no-position-error-state": { "action": "eval_sync", "expression": "JSON.stringify({unitCoverage:'usePerpsPositionForAsset non-EVM selected account returns empty state'})", "assert": { "operator": "eq", "field": "unitCoverage", "value": "usePerpsPositionForAsset non-EVM selected account returns empty state" }, "next": "ac4-screenshot-no-position-error-state" }, "ac4-screenshot-no-position-error-state": { "action": "screenshot", "filename": "evidence-ac4-no-position-error-state.png", "note": "AC4: recipe paired with unit test coverage for non-EVM selected account empty position state", "next": "teardown-done" }, "teardown-done": { "action": "end", "status": "pass" } } } } } ``` </details> ## **Recipe Workflow** <details> <summary>workflow.mmd</summary> ```mermaid flowchart TD %% TAT-3093 non-EVM selected account does not crash Perps Trending __entry__(["ENTRY"]) --> node_setup_select_non_evm_account node_setup_select_non_evm_account["setup-select-non-evm-account<br/>eval_sync"] node_setup_assert_selected_account_non_evm["setup-assert-selected-account-non-evm<br/>eval_sync"] node_setup_open_btc_market[["setup-open-btc-market<br/>perps/market-discovery"]] node_ac2_assert_market_visible["ac2-assert-market-visible<br/>wait_for"] node_ac2_assert_no_valierror["ac2-assert-no-valierror<br/>log_watch"] node_ac2_screenshot_market_visible["ac2-screenshot-market-visible<br/>screenshot"] node_ac1_assert_selected_group_evm["ac1-assert-selected-group-evm<br/>eval_sync"] node_ac1_screenshot_selected_group_evm["ac1-screenshot-selected-group-evm<br/>screenshot"] node_ac3_assert_perps_hooks_audited["ac3-assert-perps-hooks-audited<br/>eval_sync"] node_ac3_screenshot_audit_surface["ac3-screenshot-audit-surface<br/>screenshot"] node_ac4_assert_no_position_error_state["ac4-assert-no-position-error-state<br/>eval_sync"] node_ac4_screenshot_no_position_error_state["ac4-screenshot-no-position-error-state<br/>screenshot"] node_teardown_done(["teardown-done<br/>PASS"]) node_setup_select_non_evm_account --> node_setup_assert_selected_account_non_evm node_setup_assert_selected_account_non_evm --> node_setup_open_btc_market node_setup_open_btc_market --> node_ac2_assert_market_visible node_ac2_assert_market_visible --> node_ac2_assert_no_valierror node_ac2_assert_no_valierror --> node_ac2_screenshot_market_visible node_ac2_screenshot_market_visible --> node_ac1_assert_selected_group_evm node_ac1_assert_selected_group_evm --> node_ac1_screenshot_selected_group_evm node_ac1_screenshot_selected_group_evm --> node_ac3_assert_perps_hooks_audited node_ac3_assert_perps_hooks_audited --> node_ac3_screenshot_audit_surface node_ac3_screenshot_audit_surface --> node_ac4_assert_no_position_error_state node_ac4_assert_no_position_error_state --> node_ac4_screenshot_no_position_error_state node_ac4_screenshot_no_position_error_state --> node_teardown_done ``` </details> [TAT-3093]: https://consensyssoftware.atlassian.net/browse/TAT-3093?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes how Perps derives the user address/accountId across several hooks/views; incorrect selection could lead to missing/incorrect perps data or filtering, but scope is limited and covered by updated tests. > > **Overview** > Prevents Perps crashes when a non-EVM account is selected by switching Perps UI/hooks from `selectSelectedInternalAccountFormattedAddress` to a new selector, `selectSelectedAccountGroupEvmInternalAccount`, which returns the EVM account from the selected multichain account group. > > Updates Perps transactions, order-fee, close-all calculations, position-for-asset, and transaction-history flows to use the group EVM address (and derive CAIP `accountId` from it), and adds test coverage for non-EVM-selected and no-EVM-in-group scenarios plus updated account-tree fixtures. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit fbd28d5. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
## **Description**
<!--
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 adds support for auto slippage for RWA tokens
COW swap liquidity is volatile and to address it, cow swap provides
dynamic slippage suggestion service in there SDK.
Bridge api is using it. On extension and mobile, we are providing auto
option by default when one or both tokens are RWA (same is implemented
for solana tokens)
When it is auto, dynamic slippage is applied.
We also want user to have freedom to choose slippage. Hence we have kept
existing options to choose along with auto.
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: Added auto slippage support for RWA tokens
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<img width="482" height="761" alt="image"
src="https://github.com/user-attachments/assets/ffc63af5-3d7a-485a-863e-941e5b545458"
/>
## **Pre-merge author checklist**
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Changes default slippage behavior for same-chain EVM swaps when a
stock-class RWA token is involved, which can affect quote execution
outcomes and UX. Risk is mitigated by gating on the RWA remote feature
flag and adding targeted unit/integration tests.
>
> **Overview**
> Adds a new `selectIsRwaSwap` selector (same-chain EVM + stock RWA
token + RWA flag enabled) and uses it to treat those swaps like Solana
same-chain swaps for slippage.
>
> When `selectIsRwaSwap` is true, `useInitialSlippage` now initializes
slippage to `DEFAULT_SLIPPAGE_RWA` (*undefined* → provider dynamic
slippage) and `useSlippageConfig` injects an `auto` preset
(`['auto','0.5','2']`) into the slippage options.
>
> Refactors stock-RWA detection into shared `isStockRwaBridgeToken`,
forwards `rwaData` through Token Details swap navigation, and
adds/updates tests covering the new selector and slippage behavior
(including a BridgeView RWA swap case).
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
2bec59e. 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: metamaskbot <metamaskbot@users.noreply.github.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
## **Description**
Create selectors to be used for the Accounts v4 API migration of the
Activity list
Part of breaking down the PR into smaller chunks
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: null
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk: adds two small selectors and unit tests without changing
existing selection logic or mutating state. Main risk is minor
formatting/edge cases when converting hex chain IDs to CAIP strings.
>
> **Overview**
> Adds `selectEvmAddress` to return the currently selected account
address *only* when the selected internal account is EVM (otherwise
`undefined`).
>
> Adds `selectEvmEnabledCaipNetworks` to expose enabled EVM networks as
CAIP chain IDs by converting the hex `eip155` chain IDs returned from
`selectEVMEnabledNetworks` into decimal CAIP strings, with focused unit
tests for both selectors.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
c7dac4b. 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 Agent <cursoragent@cursor.com>
## **Description**
This PR bumps **`@metamask/design-system-react-native`** from **0.21.0**
to **0.22.0** (with **`@metamask/design-system-shared`** 0.14.0 → 0.15.0
via the lockfile).
**0.22.0** changes the design-system **`TextField`** and
**`TextFieldSearch`** contract: native `TextInput` props must be passed
under **`inputProps`**, imperative access to the real input uses
**`inputRef`** instead of **`ref`**, root **`ref`** targets the outer
container, **`placeholderTextColor`** is not supported on the public
`TextField` API, and spellings like **`isReadonly`** are normalized to
**`isReadOnly`** in the design system (not used in these edits).
This branch updates every in-repo consumer that imports **`TextField` /
`TextFieldSearch`** from **`@metamask/design-system-react-native`** so
types and runtime behavior match the new API (Login, OAuth rehydration,
choose/reset password, manual backup, rewards onboarding referral field,
reveal SRP password entry, trending explore search, and card
authentication). **`CardAuthentication`** now imports **`TextField`**
from the design system and uses the same **`inputProps`** split so
**`yarn lint:tsc`** stays green after the upgrade.
Unit tests were adjusted where they assumed the old structure
(**`CardAuthentication`** helpers; **`OnboardingMainStep`** mock
forwards **`inputProps.testID`** to the inner input).
---
## **Changelog**
CHANGELOG entry: null
---
## **Related issues**
Fixes:
---
## **Manual testing steps**
```gherkin
Feature: Design system 0.22 TextField usage
Scenario: User unlocks with password on Login
Given the app shows the Login screen with password field
When the user enters a password and submits unlock
Then unlock proceeds as before and the password field still accepts input and device auth affordances behave as before
Scenario: User sets password during onboarding
Given the app shows Choose Password (or Reset Password) with new and confirm fields
When the user fills both fields and moves focus between fields (e.g. Next on keyboard)
Then focus and submit behavior match expectations and no layout regressions appear on the fields
Scenario: User completes card email/password or OTP step
Given the app shows Card authentication (email/password or OTP)
When the user types in email, password, or OTP fields and toggles password visibility
Then values update correctly and login/OTP actions still work
Scenario: User enters a rewards referral code (if that flow is enabled)
Given Rewards onboarding shows the referral code field
When the user types up to six characters
Then validation and UI feedback behave as before
Scenario: User searches on Explore (interactive search bar)
Given Trending Explore shows the interactive search bar
When the user types a query and uses clear/cancel
Then search text and clear behavior work as before
```
---
## **Screenshots/Recordings**
### **Before**
### **After**
<img width="1290" height="2796" alt="Simulator Screenshot - iPhone 15
Pro Max - 2026-04-30 at 15 14 50"
src="https://github.com/user-attachments/assets/5eaa6a0c-0384-4785-afaf-6a85c453264f"
/>
<img width="1290" height="2796" alt="Simulator Screenshot - iPhone 15
Pro Max - 2026-04-30 at 15 15 08"
src="https://github.com/user-attachments/assets/ad218056-db61-449f-8335-e7250f5392d6"
/>
---
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- [ ] I've tested with a power user scenario
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
---
## **Pre-merge reviewer checklist**
*(Reviewer completes.)*
- [ ] 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**
> Updates a shared UI dependency and refactors multiple
password/authentication inputs (login, reset/choose password, card auth,
OAuth rehydration), so regressions in text entry, focus/submit behavior,
and testIDs are possible despite mostly mechanical changes.
>
> **Overview**
> Bumps `@metamask/design-system-react-native` to `0.22.0` (and
`@metamask/design-system-shared` via lockfile), and migrates in-app
consumers to the new `TextField`/`TextFieldSearch` API.
>
> All affected screens now pass native `TextInput` props via
`inputProps` and use `inputRef` for imperative focus/clear, with updates
to testIDs and E2E selectors (notably Explore/Trending search) to target
the inner text input.
>
> Adjusts unit tests/mocks to align with the new component contract
(e.g., `inputProps.testID` forwarding and simpler value assertions).
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
6815add. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
🚀 RC Builds Ready for Testing
More Info
🛡️ Build Environment
API URLs & Details
Build Flags:
AI Test Plan
Executive SummaryRelease Focus: Major UI overhaul introducing tabbed Discovery/Explore experience, new Perps Trading Campaign rewards system, and significant refactoring of the Wallet home screen, Unified Transactions View, and QR Hardware wallet scanning. Key Changes:
Critical Areas: HomepageDiscoveryTabs tab switching and Perps WebSocket lifecycle management, Unified Transactions View pagination and infinite scroll correctness, Wallet home screen animated header and MoneyBalanceCard integration, QR Hardware wallet scanning error states and recovery flows, Perps Trading Campaign rewards navigation and data loading, Explore/TrendingView tab rendering, search, and section data feeds Overall Risk: HIGH Recommendation: Conditional go — the breadth of changes (1000 files, +56k/-18k lines) across core navigation, transaction history, wallet home, and hardware wallet flows introduces substantial regression risk. Focused exploratory testing on the Wallet home screen, Unified Transactions View, HomepageDiscoveryTabs, and QR Hardware scanner is required before release. All critical paths for send, receive, and transaction history must pass on both iOS and Android. Release Scenarios (19)High Risk Scenarios (12)1. Wallet Home Screen / HomepageDiscoveryTabsRisk Level: HIGH Why This Matters: Homepage.tsx was refactored to accept a perpsProvidersHoisted prop and wrapped in forwardRef with HomepageProps. HomepageDiscoveryTabs.tsx is a brand-new 443-line component managing shared Perps providers, animated tab switching, and gradient backgrounds. The Wallet index.tsx added Reanimated shared values, useSafeAreaInsets, and a new animatedHeaderStyle with translateY/marginBottom/opacity — any regression here breaks the primary user-facing screen. Preconditions:
Test Steps:
Expected Outcomes:
2. Unified Transactions View / Activity TabRisk Level: HIGH Why This Matters: UnifiedTransactionsView.tsx was completely refactored: replaced selectSortedEVMTransactionsForSelectedAccountGroup with a new useTransactionsQuery hook providing paginated infinite scroll, added FlashList ViewToken visibility config, introduced new TransactionViewModel/UnifiedItem types, and removed filterDuplicateOutgoingTransactions. The new helpers/transformations.ts and helpers/adapters.ts files handle merging and adapting transactions. Any bug in pagination, deduplication, or the new selector (selectLocalTransactions, selectRelatedChainIdsByTransactionId) will break the activity view. Preconditions:
Test Steps:
Expected Outcomes:
3. QR Hardware Wallet ScanningRisk Level: HIGH Why This Matters: AnimatedQRScanner.tsx was significantly rewritten (+258/-43 lines): added QRHardwareScanError type system, buildQrHardwareWalletErrorAnalyticsProperties function, a full error UI with errorContainer/errorTitle/errorBody/errorFooter styles, QR_HARDWARE_LEARN_MORE_URL constant, scanError state, scanErrorActiveRef, and split reset into resetDecoder + reset. The onQRHardwareScanError and onModalHideComplete callbacks are new. Any regression in the error state machine could leave users stuck unable to use hardware wallets. Preconditions:
Test Steps:
Expected Outcomes:
4. Perps Trading Campaign / RewardsRisk Level: HIGH Why This Matters: PerpsTradingCampaignDetailsView.tsx (458 lines), PerpsTradingCampaignStatsView.tsx (306 lines), PerpsTradingCampaignLeaderboardView.tsx (143 lines), and PerpsTradingCampaignWinningView.tsx (80 lines) are all brand new. New hooks useGetPerpsTradingCampaignLeaderboard, useGetPerpsTradingCampaignLeaderboardPosition, useGetPerpsTradingCampaignVolume, usePerpsTradingCampaignParticipantOutcome, and useCampaignParticipantOutcome are all new. The sessionWinningViewAutoNavCampaignIds Set is a new session-level navigation guard that could cause issues if not reset correctly. Preconditions:
Test Steps:
Expected Outcomes:
5. Explore / TrendingView Tab ArchitectureRisk Level: HIGH Why This Matters: The entire TrendingView architecture was replaced: sections.config.tsx (520 lines) was deleted, replaced by 6 new tab files (NowTab, SportsTab, CryptoTab, DappsTab, MacroTab, RwasTab) plus ExplorePageV1.tsx, and ~15 new feed provider files. New hooks useExploreRefresh, useFeedRefresh, usePerpsFeed, usePredictionsFeed, useSportsMarketsFeed, useTokensFeed, useStocksFeed, useSitesFeed were all created. The search system was also rewritten (useExploreSearch.ts deleted and replaced). Any regression in the feed data flow or tab rendering breaks the entire Explore experience. Preconditions:
Test Steps:
Expected Outcomes:
6. Send Flow / Recipient ValidationRisk Level: HIGH Why This Matters: New hooks useFirstTimeInteractionSendAlert.tsx (102 lines), useTokenContractSendAlert.ts (85 lines), and useSendAlerts.ts (50 lines) were added. send-alert-modal.tsx was significantly expanded (+112 lines). send-address-validations.ts had 28 lines removed. The recipient.tsx component was modified (+23/-10 lines). These changes to the send validation pipeline could introduce false positives/negatives in address validation or break the alert display flow. Preconditions:
Test Steps:
Expected Outcomes:
7. Perps Home View / Market ListRisk Level: HIGH Why This Matters: PerpsHomeView.tsx had +77/-12 lines changed. HyperLiquidProvider.ts was significantly refactored (+102/-66 lines). HyperLiquidSubscriptionService.ts was heavily modified (+217/-41 lines). PerpsStreamManager.tsx had +42/-8 lines changed. usePerpsDepositProgress, usePerpsDepositStatus, usePerpsMarketListView, useWithdrawValidation all had significant changes. The PerpsController.test.ts shows 26 new test cases. These changes to the core Perps data pipeline could break live trading data. Preconditions:
Test Steps:
Expected Outcomes:
8. Account Selector / Account ManagementRisk Level: HIGH Why This Matters: AccountSelector.tsx was heavily refactored (+95/-156 lines, removing 45 lines of styles). AccountsMenu.tsx was modified. EditMultichainAccountName.tsx had significant changes (+46/-29 lines, removing 49 lines of styles). RevealSRP.tsx was refactored (+75/-47 lines, removing 52 lines of styles). The confirmations AccountSelector.tsx had +70/-35 lines changed. These are core account management flows that affect all users. Preconditions:
Test Steps:
Expected Outcomes:
9. Bridge FlowRisk Level: HIGH Why This Matters: BridgeView/index.tsx had +99/-13 lines changed. New useInsufficientNativeReserveError hook (103 lines) was added. BridgeQuoteDataContext.tsx (40 lines) is a new context provider. useBridgeQuoteData/index.ts had +69/-36 lines changed. useBridgeQuoteRequest had +12/-1 lines. SwapsConfirmButton had +23/-9 lines. These changes to the bridge quote and validation pipeline could break the bridge flow. Preconditions:
Test Steps:
Expected Outcomes:
10. Ramp / Buy FlowRisk Level: HIGH Why This Matters: Checkout.tsx is a new 54-line component. HeadlessHost.tsx was significantly refactored (+11/-48 lines). useTransakRouting.ts had +87/-8 lines changed. sessionRegistry.ts is a new 105-line session management system. headless/types.ts was modified. These changes to the Ramp headless architecture could break the buy flow for users. Preconditions:
Test Steps:
Expected Outcomes:
11. Predict / Polymarket IntegrationRisk Level: HIGH Why This Matters: PredictPreviewSheetContext.tsx was significantly expanded (+107/-32 lines). usePredictLivePositions.ts had +135/-35 lines changed. usePredictBuyError.ts was heavily refactored (+187/-74 lines) with new error source tracking. WebSocketManager.ts had +22/-4 lines. PredictFeed.tsx had +42/-31 lines. useDiscoveryScrollManager.ts is a new 201-line hook. These changes to the core Predict data and error handling pipeline could break the prediction market experience. Preconditions:
Test Steps:
Expected Outcomes:
12. Deep Links / NavigationRisk Level: HIGH Why This Matters: Routes.ts had +14/-1 lines adding many new route constants. clearStackNavigatorOptions.ts is a new 28-line utility. handleSocialLeaderboardUrl.ts, handleUniversalLink.ts, and handleRewardsUrl.ts were all modified. MainNavigator.js had +37/-10 lines. deeplinks.ts had +2 lines. Any misconfiguration in the navigation stack for new routes could cause crashes or incorrect navigation behavior. Preconditions:
Test Steps:
Expected Outcomes:
Medium Risk Scenarios (7)1. WhatsHappening Detail ViewRisk Level: MEDIUM Why This Matters: WhatsHappeningDetailView.tsx is a brand new 283-line component with complex scroll management (CARD_WIDTH calculation, SNAP_INTERVAL, hasScrolledToInitial ref). WhatsHappeningExpandedCard.tsx (214 lines), WhatsHappeningSourcesBottomSheet.tsx (86 lines), PageIndicator.tsx (50 lines), AssetRow.tsx (83 lines), TokenRow.tsx (97 lines), PerpsRow.tsx (61 lines) are all new. The WhatsHappeningSection was also significantly modified (+80/-50 lines). Preconditions:
Test Steps:
Expected Outcomes:
2. Token List / Asset DisplayRisk Level: MEDIUM Why This Matters: TokenListItem.tsx was heavily refactored (+126/-119 lines). TokenList.tsx had +19/-7 lines. Tokens/index.tsx had +16/-3 lines. AssetLogo.tsx had +17/-1 lines. AssetOverviewContent.tsx had +22/-1 lines. useTokenTransactions.ts had +5/-4 lines. These changes to the core token display components could affect how all users see their portfolio. Preconditions:
Test Steps:
Expected Outcomes:
3. Browser / Sites ManagementRisk Level: MEDIUM Why This Matters: SiteRowItem.tsx was significantly refactored (+76/-26 lines). SiteRowItemWrapper.tsx was completely deleted (29 lines removed). SitesList.tsx had +31/-6 lines. SitesFullView.tsx had +48/-10 lines. New hooks useBrowserFavoritesSites (57 lines) and useBrowserRecentsSites (74 lines) were added. useSitesData.ts had +35/-19 lines. The deletion of SiteRowItemWrapper could cause crashes if any component still references it. Preconditions:
Test Steps:
Expected Outcomes:
4. Backup Vault / SecurityRisk Level: MEDIUM Why This Matters: backupVault.ts had +14/-1 lines with new test coverage (26 new test cases). ChoosePassword/index.tsx had +26/-27 lines. Login/index.tsx had +12/-9 lines. ResetPassword/index.tsx had +28/-24 lines. ManualBackupStep1/index.tsx had +9/-8 lines. RevealPrivateCredential/PasswordEntry.tsx had +11/-12 lines. These are critical security flows where any regression could lock users out of their wallets. Preconditions:
Test Steps:
Expected Outcomes:
5. Ledger Hardware WalletRisk Level: MEDIUM Why This Matters: LedgerSelectAccount/index.tsx had +20/-6 lines changed with 151 new test lines. HardwareWallet/AccountSelector/index.tsx had +5/-10 lines with new testIds. ConnectQRHardware/index.test.tsx had +70/-58 lines. These changes to hardware wallet flows could break Ledger connectivity for users who rely on hardware wallets for security. Preconditions:
Test Steps:
Expected Outcomes:
6. Notifications / SettingsRisk Level: MEDIUM Why This Matters: NotificationsSettings.view.test.tsx has 200 new test lines indicating significant new behavior. NotificationsView.view.test.tsx has 169 new test lines. BackupAndSyncFeaturesToggles.tsx had +7/-7 lines. BackupAndSyncToggle.tsx had +6/-5 lines. ConfirmTurnOnBackupAndSyncModal.tsx had +5/-7 lines. These changes to notification and sync settings could affect user data backup behavior. Preconditions:
Test Steps:
Expected Outcomes:
7. Transaction Confirmation / Custom AmountRisk Level: MEDIUM Why This Matters: custom-amount-info.tsx had +42/-23 lines and custom-amount-info.styles.ts had +9/-2 lines. projected-five-year-balance.tsx is a new 56-line component. useTransactionConfirm.ts had +12/-26 lines (significant reduction suggesting refactoring). useTransactionCustomAmount.ts had +7/-14 lines. useConfirmActions.ts had +24/-4 lines. footer.tsx had +2/-5 lines. These changes to the confirmation flow could break transaction submission. Preconditions:
Test Steps:
Expected Outcomes:
Teams Sign-off Status (20/22)Signed off: Assets, BE Trade, Bots Team, Card, Confirmations, Core Extension UX, Delegation, Design System, Earn, Mobile Platform, Mobile UX, Money Movement, Networks, Onboarding, Perps, Rewards, Social & AI, Swaps and Bridge, Transactions, Wallet Integrations Awaiting sign-off (2): Accounts, Predict Excluded Features - Feature Flags Disabled (59)The following features are disabled via feature flags and should NOT be tested:
Generated by AI Test Plan Analyzer (claude-sonnet-4-6) at 2026-05-15T17:50:03.295Z AI generated test plan (JSON): Available as artifact |
Co-authored-by: Cursor <cursoragent@cursor.com>
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection:
The combination of CI infrastructure changes (which need validation that the pipeline works) and widespread app code changes touching navigation, icons, and multiple feature areas justifies running ALL test tags. The TabBar and MainNavigator changes are particularly high-risk as they are shared by every E2E test flow. Performance Test Selection: |
|
|
@SocketSecurity ignore-all |
|
policy-bot: approve |



🚀 v7.77.0 Testing & Release Quality Process
Hi Team,
As part of our new MetaMask Release Quality Process, here’s a quick overview of the key processes, testing strategies, and milestones to ensure a smooth and high-quality deployment.
📋 Key Processes
Testing Strategy
Conduct regression and exploratory testing for your functional areas, including automated and manual tests for critical workflows.
Focus on exploratory testing across the wallet, prioritize high-impact areas, and triage any Sentry errors found during testing.
Validate new functionalities and provide feedback to support release monitoring.
GitHub Signoff
Issue Resolution
Cherry-Picking Criteria
🗓️ Timeline and Milestones
✅ Signoff Checklist
Each team is responsible for signing off via GitHub. Use the checkbox below to track signoff completion:
Team sign-off checklist
This process is a major step forward in ensuring release stability and quality. Let’s stay aligned and make this release a success! 🚀
Feel free to reach out if you have questions or need clarification.
Many thanks in advance
Reference