Repository navigation
release: 13.54.0 - #47119
release: 13.54.0#47119
Conversation
## **Description** This PR solves two related problems: 1. For a very long time, `yarn start`/`yarn build:dev` would start the wallet with Sepolia selected, There was an ask for it to start with `All networks`, just like the prod build does. 2. When we recently added Arc to the list of networks in the Config Registry, it would change the user's currently selected network to Arc. This could happen either on a brand new wallet, or on a wallet that got upgraded. I made new rules: **A.** If exactly one network is enabled, do not change it **B.** If all networks are enabled, add the new network to the list Also moved the function `isInE2eTest()` from `ui/contexts/hardware-wallets/is-in-e2e-test.ts` to `shared/lib/environment.ts`. This is the cause of many of the "Files changed" and the cause of most of the CODEOWNERS requirements. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MWPE-748 MWPE-748 #done <!--## **Manual testing steps** ## **Screenshots/Recordings** ## **Pre-merge author checklist** ## **Pre-merge reviewer checklist**--> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes default network enablement for fresh installs and dev builds plus async restore logic when Config Registry auto-adds chains—user-visible network selection with regression tests but broad behavioral impact. > > **Overview** > **Fresh wallets and dev builds now start in “All popular networks” mode** instead of pre-enabling Sepolia (debug/testing) or a fixed featured set. `NetworkEnablementController` initializes with every known network disabled, then calls `enableAllPopularNetworks()` for non-test installs that have no persisted enablement map; `IN_TEST` still defaults to **Localhost only**. > > **Config Registry auto-enabled networks (e.g. Arc) no longer hijack the network filter.** On `NetworkController:networkAdded`, when the chain is registry-marked `isAutoEnabled`, init waits for enablement then **`restoreEnabledNetworkMap`** to the prior map so a single-network selection stays put and “all on” mode only adds the new chain as disabled until the user opts in. > > **Test/E2E support:** `isInE2eTest()` moves to `shared/lib/environment`; fixture-less E2E builds get Localhost via `initializeWallet`; LLM fixtures use the fixture store when `fixtureServerPort` is set and default fixtures disable sync/external services. New unit and E2E coverage for the above behaviors. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit e66b176. 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 the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **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** No manual testing steps ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Updates profile-sync and cryptography dependency boundaries (Web Crypto via LavaMoat) without local code changes; behavior changes come only from the upstream controller release. > > **Overview** > Bumps **`@metamask/profile-sync-controller`** from `^33.0.0` to **`^34.0.3`** in `package.json` and refreshes **`yarn.lock`**. > > The new controller release routes crypto through **`@metamask/cryptography`** instead of **`@noble/ciphers`**, pulls in **`@metamask/seedless-onboarding-controller@^12.0.0`** (and related transitive packages such as analytics/config-registry controllers), and updates other deps (e.g. **`immer`**, **`@noble/curves`**). There are **no application source changes**—only dependency and LavaMoat policy updates. > > All **eight** webpack LavaMoat **`policy.json`** files (MV2/MV3 × main/beta/flask/experimental) add allowances for **`@metamask/profile-sync-controller>@metamask/cryptography`** (`crypto.getRandomValues` and **`crypto.subtle`** encrypt/decrypt/importKey), wire that package into the profile-sync-controller entry, drop **`@noble/ciphers`**, and allow **`@metamask/utils>pony-cause`** where utils is used in that graph. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 5d0fdbc. 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: MetaMask Bot <metamaskbot@users.noreply.github.com>
) ## **Description** ### Context All [Vault Corruption Detected](https://mixpanel.com/project/2212883/view/2760759/app/boards#id=10932487&edited-bookmark=zGCMqkScpJLk) events have the Browser property as `not set` in Mixpanel. ### Problem Events tracked through `trackEarlySegmentEvent` (Vault Corruption Detected, critical errors, state migration events) fire before `AnalyticsController` is initialized. They are sent to Segment with a minimal context containing only `app`, so they never carry `context.userAgent`. Segment's server-side enrichment parses `context.userAgent` to derive the browser name and version (delivered to Mixpanel as the `Browser` / `Browser Version` properties), so without it the browser shows as `not set` for these events. ### Solution - Extract the existing inline userAgent read from `createEnrichmentContext` into a shared `getUserAgent()` helper in the platform adapter. - Populate `context.userAgent` in `trackEarlySegmentEvent` using that helper, matching how standard enriched events carry it. - Update the colocated unit tests that assert exact Segment payload context. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: none ## **Manual testing steps** 1. Run the extension (`yarn start`) and load it in Chrome. 2. Opt in to MetaMetrics (so early events can be tracked). 3. Trigger a vault corruption event locally. 4. Observe the outgoing Segment `track` payload (e.g. via the Segment debugger). 5. Verify `context.userAgent` is populated with `navigator.userAgent` instead of being absent. ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Analytics context enrichment only; no changes to auth, vault handling, or event consent gating. > > **Overview** > Early Segment events (vault corruption, critical errors, state migrations) now include **`context.userAgent`** so Mixpanel can show Browser instead of `not set`. > > A shared **`getUserAgent()`** helper was extracted from the platform adapter enrichment context (empty string when there is no `window`, e.g. MV3 service worker). **`trackEarlySegmentEvent`** uses it in its default context, aligned with normal AnalyticsController-enriched payloads. **`createEnrichmentContext`** now calls the same helper instead of inlining the read. > > Unit tests that assert full Segment `track` payloads were updated to expect **`userAgent`** in `context`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit bd1b150. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Cursor <cursoragent@cursor.com>
#46973) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This PR does bump stellar-wallet-snap from 1.1.0 to 1.1.1 Fix the issue that memo show when sending contract base token , it shouldnt show, becoz memo is not allowed when sending contract base token https://www.loom.com/share/f0f6a5ad706b49bab10beedbacade985 <!-- 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: Bump stellar-wallet-snap from 1.1.0 to 1.1.1 ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Patch-level dependency-only update with no extension code changes; Stellar snap behavior may differ only per the snap package’s 1.1.1 release notes. > > **Overview** > Bumps the **`@metamask/stellar-wallet-snap`** dependency from **1.1.0** to **1.1.1** in `package.json` and refreshes **`yarn.lock`** so installs resolve to the new package version and checksum. > > There are **no application or source changes** in this PR—only the dependency pin and lockfile. The extension still bundles the Stellar snap via the existing preinstalled snap wiring. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit cc88b76. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## Version Bump After Release This PR bumps the main branch version from 13.53.0 to 13.54.0 after cutting the release branch. ### Why this is needed: - **Nightly builds**: Each nightly build needs to be one minor version ahead of the current release candidate - **Version conflicts**: Prevents conflicts between nightlies and release candidates - **Platform alignment**: Maintains version alignment between MetaMask mobile and extension - **Update systems**: Ensures nightlies are accepted by app stores and browser update systems ### What changed: - Version bumped from `13.53.0` to `13.54.0` - Platform: `extension` - Files updated by `set-semvar-version.sh` script ### Next steps: This PR should be **manually reviewed and merged by the release manager** to maintain proper version flow. ### Related: - Release version: 13.53.0 - Release branch: release/13.53.0 - Platform: extension - Test mode: false --- *This PR was automatically created by the `create-platform-release-pr.sh` script.* Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
release: sync stable to main for version 13.51.0
…6936) ## **Description** When a hardware wallet device is locked (e.g. a Ledger that hasn't been unlocked), the error modal previously showed multi-step recovery instructions telling the user to unlock the device and then reconnect. This was unnecessarily verbose for a simple state — the user only needs to unlock the device and retry. The change simplifies the `AuthenticationDeviceLocked` error case in `buildErrorContent`: - **Before:** `variant: 'recovery'` with two bullet-point instructions (`hardwareWalletErrorRecoveryUnlock1`, `hardwareWalletErrorRecoveryUnlock2`) - **After:** `variant: 'description'` with a single, concise description: *"Unlock it and try again to continue"* (`hardwareWalletErrorDeviceLockedDescription`) The lock icon is preserved. The repair link remains hidden for this error code. The modal layout switches from the multi-step recovery format to the simpler description format used by other acknowledge-only errors. ## **Changelog** CHANGELOG entry: Simplified the locked device error modal into a single unlock description instead of multi-step recovery instructions ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MUL-2232?atlOrigin=eyJpIjoiNTgxYjVmZDkzODk4NGEyNGI4Mzc5ODBlNjdlNzkxZGIiLCJwIjoiaiJ9 ## **Manual testing steps** 1. Connect a hardware wallet (e.g. Ledger) 2. Lock the device while it's connected 3. Initiate an action that requires the device (e.g. signing a transaction) 4. Verify the error modal shows a lock icon, title with the wallet type, and the description "Unlock it and try again to continue" — without multi-step recovery instructions ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <img width="546" height="981" alt="Screenshot 2026-10-08 at 19 27 51" src="https://github.com/user-attachments/assets/2c755b05-643a-4e17-9c33-212091603747" /> <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. PRBODY )" <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Copy and modal layout only for one hardware-wallet error code; retry/reconnect behavior is unchanged. > > **Overview** > When a hardware wallet is locked (`AuthenticationDeviceLocked`), the error modal no longer uses the **recovery** layout with two unlock bullet steps. It now uses the simpler **description** layout with one line: *"Unlock it and try again to continue"* (`hardwareWalletErrorDeviceLockedDescription`), added in `en` and `en_GB` locales. > > The lock icon and device-locked title are unchanged; repair link behavior for this error is unchanged. Unit tests in `error-content-builder` and `hardware-wallet-error-modal` assert the new copy and that the old recovery unlock strings are not shown. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 396a9fe. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** Upgrade `@metamask/perps-controller` from 17.1.0 to 20.0.0 (MV2/MV3 LavaMoat policies regenerated; no further policy changes from 19 to 20). Fee previews now match what the controller charges: - **Shared notional helper.** Order entry, close, close-all, reverse, auto-close and TP/SL use one helper to derive the USD notional passed to the controller fee quote and refetch when it changes. Close-all quotes each symbol using the combined batch notional. Since controller 18, bounded subscription waivers depend on size. - **Fees from the controller quote.** Resolved rates, the VIP badge and the struck-through original rate come from controller 20's quote metadata. The badge shows only when the quote is reduced. The hook and close-all share one pure function to apply rewards discounts only to local fallbacks. - **Controller 20 changes.** Missing realized PnL displays as Unknown (zero stays zero); the error map includes `ORDER_SCALE_PREVIEW_STALE`. Validation: unit tests for every preview (discounted, undiscounted, full and blended waivers, rewards-lookup disagreement), TypeScript, lint, LavaMoat. Read-only live proof (dev1 testnet BTC long, 3x, USD 100 and 1000, HUD on) passes 43/43 on controller 19 and on this branch. No fixture account currently has a positive discount (10 fixtures checked on testnet, then mainnet read-only), so the discounted path is proven by the unit tests; no order, close or signature was submitted. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: [TAT-4063](https://consensyssoftware.atlassian.net/browse/TAT-4063) ## **Manual testing steps** 1. Load the updated extension and unlock a wallet with Perps enabled. 2. Open Perps in the fullscreen wallet. 3. Confirm the account balance and market watchlist load with prices. 4. Open positions, orders, and transaction history; confirm each view loads without errors. 5. For a history entry whose liquidation metadata omits the user address, confirm its other trade information remains visible and it does not show an account-specific “Liquidated” badge. 6. Open an order preview and enter an amount. Confirm the fee estimate updates and any rewards/subscription discount is applied once; leave the order unsubmitted. 7. With existing positions, open the close-all confirmation. Confirm its fee estimate loads and reflects each position size; leave the close action unsubmitted. ## **Screenshots/Recordings** Current rebased-source controller20 home and shared-helper fee preview proof; no trade mutations. <table> <tr><td align="center" valign="top" width="50%"><strong>Current Perps home</strong><br/><img src="https://raw.githubusercontent.com/abretonc7s/mm-extension-farm-artifacts/main/fixes/46934/recipe-run/screenshots/ac2-home.png?sha=42214ad6391774bc" alt="Current Perps home" width="320" /></td><td align="center" valign="top" width="50%"><strong>BTC USD100 fee with HUD</strong><br/><img src="https://raw.githubusercontent.com/abretonc7s/mm-extension-farm-artifacts/main/fixes/46934/fee-preview-run/screenshots/btc-100-fee.png?sha=9db6d320f5a01fcb" alt="BTC USD100 fee with HUD" width="320" /><br/><sub>caption confidence: LOW — generic filename — no state-specific suffix</sub></td></tr> <tr><td align="center" valign="top" width="50%"><strong>BTC USD1000 fee with HUD</strong><br/><img src="https://raw.githubusercontent.com/abretonc7s/mm-extension-farm-artifacts/main/fixes/46934/fee-preview-run/screenshots/btc-1000-fee.png?sha=8d707699d820cd95" alt="BTC USD1000 fee with HUD" width="320" /><br/><sub>caption confidence: LOW — generic filename — no state-specific suffix</sub></td><td align="center" valign="top" width="50%"><strong>Existing SOL close-all fee with HUD</strong><br/><img src="https://raw.githubusercontent.com/abretonc7s/mm-extension-farm-artifacts/main/fixes/46934/fee-preview-run/screenshots/close-all-fee.png?sha=f4185b15d4122f96" alt="Existing SOL close-all fee with HUD" width="320" /><br/><sub>caption confidence: LOW — generic filename — no state-specific suffix</sub></td></tr> </table> ## **Validation Recipe** <details><summary>recipe.json (14 nodes — TAT-4063 Perps controller 19.0.0 proof)</summary> ```json { "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json", "title": "TAT-4063 Perps controller 19.0.0 proof", "description": "Read-only live regression guard followed by the new dependency-version assertion. Derived AC3 is corroborated outside this runtime recipe.", "workflow": { "entry": "setup-status", "nodes": { "setup-status": { "action": "app.status", "next": "setup-cdp", "intent": "Resolve the Extension checkout and adapter status before Perps proof" }, "setup-cdp": { "action": "cdp.target", "required": true, "timeout_ms": 15000, "next": "setup-ensure-unlocked", "intent": "Confirm the Extension CDP runtime is reachable" }, "setup-ensure-unlocked": { "action": "metamask.wallet.ensure_unlocked", "timeout_ms": 45000, "next": "setup-open-perps", "intent": "Ensure the wallet is unlocked before opening Perps" }, "setup-open-perps": { "action": "ui.navigate", "next": "setup-perps-ready", "intent": "Show the Perps home surface", "hash": "#/perps-home" }, "ac2-read-positions": { "action": "metamask.perps.read_positions", "next": "ac2-read-orders", "intent": "Read live Perps positions without mutating account state" }, "ac2-read-orders": { "action": "metamask.perps.read_orders", "next": "ac2-settle", "intent": "Read live Perps open orders without mutating account state" }, "gate-done": { "action": "end", "status": "pass" }, "ac2-read-home": { "action": "metamask.perps.read_visible_state", "surface": "home", "minimum_market_count": 1, "require_features": [ "balance", "market-list" ], "intent": "Observe a populated Perps home after setup", "next": "ac2-assert-home", "forbid_test_ids": [ "perps-tutorial-skip-button" ], "max_items": 200 }, "ac2-assert-home": { "action": "assert_output", "source": "ac2-read-home", "assert": { "path": "$.surface", "operator": "eq", "value": "home" }, "proves": [ "AC2" ], "intent": "The observed surface is Perps home", "next": "ac2-assert-markets" }, "ac2-assert-markets": { "action": "assert_output", "source": "ac2-read-home", "assert": { "path": "$.marketCount", "operator": "gte", "value": 1 }, "proves": [ "AC2" ], "intent": "Perps home contains market data rather than only a loading shell", "next": "ac2-read-positions" }, "ac2-settle": { "action": "ui.wait_for", "test_id": "perps-watchlist-BTC", "timeout_ms": 20000, "intent": "Show the populated account market watchlist", "next": "ac2-capture", "proves": [ "AC2" ] }, "ac2-capture": { "action": "ui.screenshot", "intent": "Preserve the read-only trading overview", "next": "ac1-version", "proves": [ "AC2" ] }, "ac1-version": { "action": "command", "cmd": "node -e 'const fs=require('\"'\"'node:fs'\"'\"');const assert=require('\"'\"'node:assert/strict'\"'\"');const manifest=require('\"'\"'./package.json'\"'\"').dependencies['\"'\"'@metamask/perps-controller'\"'\"'];const installed=require('\"'\"'./node_modules/@metamask/perps-controller/package.json'\"'\"').version;const lock=fs.readFileSync('\"'\"'yarn.lock'\"'\"','\"'\"'utf8'\"'\"');console.log(JSON.stringify({manifest,installed,lock19:lock.includes('\"'\"'resolution: \\\"@metamask/perps-controller@npm:19.0.0\\\"'\"'\"')}));assert.equal(manifest,'\"'\"'^19.0.0'\"'\"');assert.equal(installed,'\"'\"'19.0.0'\"'\"');assert.ok(lock.includes('\"'\"'resolution: \\\"@metamask/perps-controller@npm:19.0.0\\\"'\"'\"'));'", "timeout_ms": 10000, "intent": "The installed trading controller matches the requested release", "next": "gate-done", "proves": [ "AC1" ] }, "setup-perps-ready": { "action": "ui.wait_for", "test_id": "perps-watchlist-BTC", "timeout_ms": 60000, "intent": "The account watchlist is ready before checking the trading overview", "next": "ac2-read-home" } } }, "proofTargets": [ { "id": "AC1", "claim": "The Extension manifest, lockfile and installed controller resolve 19.0.0." }, { "id": "AC2", "claim": "The live Perps home remains populated and positions/orders reads succeed." } ] } ``` </details> ## **Validation Logs** <details><summary>Full output (14/14 passed, pass)</summary> ``` # MetaMask Recipe Run Status: pass Duration: 5.2s Nodes: 14/14 passed ## Side findings - REVIEW 2 distinct application warning/error event(s) (non-blocking; expanded below and stored in diagnostics.json) ## Steps - PASS setup-status (app.status, 14ms): platform=extension - PASS setup-cdp (cdp.target, 8ms): platform=extension - PASS setup-ensure-unlocked (metamask.wallet.ensure_unlocked, 341ms): proof=extension-password-unlock - PASS setup-open-perps (ui.navigate, 151ms): proof=ui-navigation - PASS setup-perps-ready (ui.wait_for, 3.3s): matched=true, cdpPort=7666, targetUrl=chrome-extension://hebhblbkkdabgoldnojllkipeoacjioc/home.html#/perps-home, cdpTargetId=9EB98A70161C9ACB2FD39A995ADBD422, runtimeSessionId=2a5d1c03-88df-4870-b00a-b6144cb1bff4 - PASS ac2-read-home (metamask.perps.read_visible_state, 149ms): platform=extension, route=#/perps-home, proof=visible-dom-accessibility - PASS ac2-assert-home (assert_output, 7ms): source=ac2-read-home, stream=stdout - PASS ac2-assert-markets (assert_output, 8ms): source=ac2-read-home, stream=stdout - PASS ac2-read-positions (metamask.perps.read_positions, 137ms): count=0, matching=0 - PASS ac2-read-orders (metamask.perps.read_orders, 130ms): count=0, matching=0 - PASS ac2-settle (ui.wait_for, 548ms): matched=true, cdpPort=7666, targetUrl=chrome-extension://hebhblbkkdabgoldnojllkipeoacjioc/home.html#/perps-home, cdpTargetId=9EB98A70161C9ACB2FD39A995ADBD422, runtimeSessionId=2a5d1c03-88df-4870-b00a-b6144cb1bff4 - PASS ac1-version (command, 36ms): exitCode=0, stdout={"manifest":"^19.0.0","installed":"19.0.0","lock19":true} - PASS gate-done (end, 0ms) ``` </details> ## **Pre-merge author checklist** - [x] Followed the repository coding guidelines. - [x] Completed the available template prose and retained validation evidence. - [x] Included focused regression tests. <!-- Labels are assigned by the publication host; no PR exists yet. --> <!-- Documentation checklist: no new public component or utility. --> <!-- ## **Pre-merge reviewer checklist** Reserved for the human reviewer after publication. --> ## **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-4063]: https://consensyssoftware.atlassian.net/browse/TAT-4063?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches trading fee display and discount logic across order/close flows; incorrect notional or double-discount would misstate fees but does not change signing paths directly. > > **Overview** > Upgrades **`@metamask/perps-controller`** to **20.0.0** (with LavaMoat policy updates for nested `@metamask/utils`) so Perps fee previews align with what submit/close paths charge. > > **Notional-aware quoting:** New `getPerpsNotionalUsd` centralizes USD notional (order amount, partial closes, close-all batch totals, reverse 2× position value, TP/SL max trigger). Order entry, close, close-all, reverse, auto-close, and update-TP/SL pass that notional into `perpsCalculateFees` / `usePerpsOrderFees` and refetch when size or prices change. > > **Discount handling:** Resolved controller quotes use `feeSource`, `metamaskFeeDiscountBips`, and `undiscountedMetamaskFeeRate` for badges and strikethrough rates—rewards are not applied twice. UI rewards discounts apply only to local RPC/timeout fallbacks via `applyPerpsFallbackDiscount` (including close-all’s per-symbol fallback split). > > **Other behavior:** Transaction history treats missing realized PnL as **Unknown** (zero PnL preserved); liquidation UI/metadata tolerates missing `liquidatedUser`; maps `ORDER_SCALE_PREVIEW_STALE` to a generic order-failed message. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 85d5ffc. 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 the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Adds the `confirmations_pay_rpc` remote feature flag and `isPayRpcTypeAllowed`, a pure helper that decides whether a dApp origin may request a MetaMask Pay type (`perpsDeposit` / `perpsWithdraw`) through the upcoming `wallet_mmPay` RPC method. No caller yet. Stack 1/7: followed by #46982. Gated by `confirmations_pay_rpc`; off by default. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: [CONF-2130](https://consensyssoftware.atlassian.net/browse/CONF-2130) ## **Manual testing steps** Nothing to try in the extension yet; the helper has no caller. Verify: 1. The extension builds and behaves as before (no flag value set means nothing changes). 2. `confirmations_pay_rpc` is listed in the feature flag registry with everything off by default. <!-- ## **Screenshots/Recordings** ### **Before** ### **After** --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. [CONF-2130]: https://consensyssoftware.atlassian.net/browse/CONF-2130?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > No runtime integration yet; missing or default flag values deny all requests, so extension behavior stays the same until later PRs connect the helper. > > **Overview** > Introduces the **`confirmations_pay_rpc`** remote feature flag (registered for CI/E2E with **empty `allowedTypes` and `dapps`**, so nothing is enabled in production by default) and **`PAY_RPC_FEATURE_FLAG`** in the known-flag constants map. > > Adds **`isPayRpcTypeAllowed`** in `shared/lib/transaction/pay-rpc.ts`: a pure gate for upcoming **`wallet_mmPay`** that requires the type in the flag’s top-level allowlist and in the requesting dApp’s config, matches origins strictly (with **`http://localhost`** matching any port), and for **`perpsWithdraw`** also requires **`confirmations_pay_post_quote`** to be enabled. **No callers in this PR**—behavior is unchanged until follow-up stacks wire the RPC. > > Unit tests cover allowlists, origin edge cases, malformed flag payloads, and withdraw gating. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit dc299d9. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
… misleading fee alerts (#46049) ## **Description** Monad enforces a protocol-level **10 MON reserve balance**. When a transaction would leave an account below that floor (especially Smart Accounts), the network rejects it. Users on extension ~13.44 were seeing **generic “insufficient network fees” / interaction failures** for dApp transactions (e.g. MON swaps) even when the real cause was the reserve rule—and even when they expected the post-tx balance to stay above 10 MON. The reserve alert was previously gated on gasless/sponsorship support, so hardware wallets and other non-relay paths never got the correct message; fee / estimate-failed alerts won instead. **Solution** - Shared Monad reserve helpers (`shared/lib/monad-reserve-balance.ts`) for mainnet + testnet - Always show the blocking reserve-balance alert when the tx is not gas-sponsored (simulation `callTraceErrors` / `simulationFails`, plus proactive `balance - value < 10 MON`) - Suppress generic insufficient-balance and gas-estimate-failed alerts when a reserve violation is the root cause - Clearer EN copy explaining ending balance + Smart Account strictness - Unrelated unblock: Shield config no longer imports removed `Env` from `@metamask/shield-controller` (was breaking confirmation unit tests) ## **Changelog** CHANGELOG entry: Fixed misleading insufficient network fee alerts on Monad when the 10 MON reserve balance requirement was the actual cause ## **Related issues** Related: #42068 <!-- Fixes: --> ## **Manual testing steps** 1. Load the extension build from this branch and switch to **Monad** (`0x8f`). 2. With an EOA holding ~12–15 MON, submit a native value spend / dApp interaction that would leave **less than 10 MON** after the transfer. 3. Confirm the confirmation shows the **Reserve balance is required** alert (10 MON), and that Confirm is blocked. 4. Confirm you do **not** see the generic “You do not have enough MON … to pay for network fees” message for that case. 5. Repeat with a spend that leaves **≥ 10 MON** remaining and verify the reserve alert does not appear. 6. If available, repeat with a **Smart Account** on Monad and confirm the reserve messaging still appears when ending balance would go below 10 MON. <!-- ## **Screenshots/Recordings** ### **Before** ### **After** --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. Made with [Cursor](https://cursor.com) --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: gabrieledm <gabriele.delmonte-ext@consensys.net> Co-authored-by: Gabriele Del Monte <37625739+gabrieledm@users.noreply.github.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Bump LavaMoat tooling to the latest version which includes bug fixes that we are interested in. More specifically includes policy generation improvements and prevents runtime errors being thrown when Chrome accesses `chrome`. Pins SES to `2.2.0` since `>=2.3.0` has a bug that prevents it from running in some versions of Chrome. ## **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** https://metamask.sentry.io/issues/7442639463/ https://consensyssoftware.atlassian.net/browse/WPC-1401 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **High Risk** > Changes the SES/LavaMoat sandbox and webpack policy surface for every production bundle; mis-generated or overly permissive policy updates could affect runtime security or break builds across all extension flavors. > > **Overview** > Upgrades **LavaMoat** (`lavamoat` **10.0.5 → ^11.1.7**) and **`@lavamoat/webpack`** (**2.2.3 patched → ^3.0.1**), dropping the Yarn patch that added webpack **≥5.107** runtime helpers (`dn`, `ns`)—those are expected to ship in the new plugin. > > Adds a root **`resolutions`** pin for **`ses` at 2.2.0** (replacing the older SES 1.x line pulled in by prior LavaMoat packages). Regenerates **LavaMoat webpack policies** for the build profile and all **MV2/MV3** variants (`beta`, `experimental`, `flask`, `main`): package keys are reshaped (e.g. `@lavamoat/webpack>lavamoat-*` → `lavamoat>lavamoat-*`), new entries appear for nested Babel/tofu deps, and many packages gain **`Float32Array` / `Float64Array`** (and related) global allowances; some stale globals (e.g. broad TypeScript language-service names) are removed. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 8957b3d. 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: MetaMask Bot <metamaskbot@users.noreply.github.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** The internal error dialog (state corruption / trouble starting) was always dark. Its styles used fixed dark greys, and the screen is shown before the app sets `html[data-theme]`. The dialog now uses theme tokens, and the background sends `PreferencesController.theme` (`light`, `dark`, or `os`) so the UI can apply it before the dialog renders. If the controller is not ready yet, the same preference is read from extension storage. <!-- 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: Fixed the internal error dialog so it follows the selected theme ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MWPE-716 ## **Manual testing steps** 1. Open MetaMask and set the theme to light in Settings. 2. Lock the wallet. 3. In the browser Application storage for the extension, delete the Keyring data. 4. On the Chrome extensions page, click Reload. 5. Open MetaMask and confirm the internal error dialog uses the light theme. 6. Repeat with dark, and with the OS theme, and confirm the dialog matches that preference. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <img width="375" height="849" alt="Screenshot 2026-10-06 at 10 56 22" src="https://github.com/user-attachments/assets/84b5766e-f7d8-4c9c-aa7b-c347d112e6b9" /> <img width="368" height="848" alt="Screenshot 2026-10-06 at 11 49 21" src="https://github.com/user-attachments/assets/657d4c97-df86-41bc-9c62-11cfb8cccd66" /> <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > UI-only changes to the critical error screen and theme application; no changes to vault recovery, auth, or persistence logic beyond passing theme in error params. > > **Overview** > The internal **trouble starting / state corruption** screen no longer stays locked to dark styling. The background now forwards **`PreferencesController.theme`** with startup error messages, and the UI applies **`html[data-theme]`** (via `setTheme`) before the dialog HTML is injected—using the passed value when available, otherwise reading **`PreferencesController`** from extension storage with a short timeout. > > Styling moves from **`errors.scss`** to **Tailwind utilities** in `getErrorHtml`, with a new **`light:`** variant (`html[data-theme="light"]`) so light mode uses semantic design tokens while dark keeps the existing brand greys. Only CSS anchor positioning for the legal popover remains in SCSS. Tests cover theme propagation and OS theme / storage fallbacks. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 42cbcf3. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…eta (#46949) ## **Description** One of the four root causes of the non-deterministic Firefox build (the `c`/`l` variable-name swaps in `runtime.js` that fail the AMO reviewers' byte-for-byte rebuild check). The mechanism shared by all four is explained in plain language [here](#46845 (comment)): anything build-specific that leaks into webpack's module hashes ends up changing the provisional chunk hashes written into `runtime.js`, which SWC's letter-frequency-based variable naming then reacts to. This PR closes one such leak. It is extracted from #46845. ### What was happening Our React Compiler wrapper collects statistics for the `--reactCompilerVerbose` report. For each function it compiles, it records an event (compiled, skipped or error, the line and column, and **the file's absolute path**) and stores the list on the module as `buildMeta.__reactCompilerStatus__`. `buildMeta` is the wrong drawer. webpack treats it as "facts about what this module is" and **includes `JSON.stringify(buildMeta)` in the module's hash**. So: ```json "__reactCompilerStatus__": { "events": [ { "filename": "/home/runner/work/metamask-extension/metamask-extension/work/i1-xxxxxx/metamask-extension/ui/contexts/assetPolling.tsx", … } ]} ``` made 1,800 module hashes depend on the build directory. Worse, they also depended on **timing**. The wrapper can only record events when it runs in the main process (it needs `this._module`, which `thread-loader` workers do not have). `thread-loader` normally runs these loaders in worker processes, but when its worker pool is unavailable it silently falls back to running them in-process. On a fast machine the pool stays alive and nothing is ever recorded. On a slow 2-core CI runner the pool goes idle and gets disposed mid-build, and a **timing-dependent subset** of modules gets the statistics recorded: ``` build 1: assetPolling.tsx → buildMeta has __reactCompilerStatus__ (path i1-xxxxxx) build 2: assetPolling.tsx → buildMeta has __reactCompilerStatus__ (path i2-xxxxxxxxxxxx) build 5: assetPolling.tsx → no __reactCompilerStatus__ at all ``` This is why this one can only be seen on CI: on a laptop it is literally not there. ### The fix Store the events on `buildInfo` instead, webpack's drawer for "things that happened while building this module", which is **not** hashed, and record the filename relative to the project root. `ReactCompilerPlugin` reads from `buildInfo` now. The verbose report is unchanged. ```diff - const buildMeta = this._module?.buildMeta + const buildInfo = this._module?.buildInfo … - filename, + filename: rootContext ? relative(rootContext, filename) : filename, … - buildMeta[REACT_COMPILER_STATUS_KEY] = { events }; + buildInfo[REACT_COMPILER_STATUS_KEY] = { events }; ``` ## **Changelog** CHANGELOG entry: null ## **Related issues** Related: [INFRA-3920](https://consensyssoftware.atlassian.net/browse/INFRA-3920) ## **Manual testing steps** 1. Run a build with the verbose report: `yarn webpack --reactCompilerVerbose` and check the React Compiler summary still prints at the end (statistics are collected only when thread-loader runs loaders in-process, same as before this PR). 2. Build the Firefox production bundle: `ENABLE_MV3=false yarn webpack:lavamoat:build:mv2 --env production` 3. Load `dist/firefox` as a temporary add-on in Firefox (`about:debugging`), unlock or onboard, and verify the UI renders normally. The emitted code is unchanged by this PR. <!-- ## **Screenshots/Recordings** ### **Before** ### **After** --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. [INFRA-3920]: https://consensyssoftware.atlassian.net/browse/INFRA-3920?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches the React Compiler loader path for ~1,800 UI modules but only changes where stats are stored, not compiled output; wrong placement could still affect hashes or verbose stats collection. > > **Overview** > Fixes **non-deterministic webpack module hashes** caused by React Compiler verbose statistics being written to `module.buildMeta`, which webpack folds into each module’s hash. > > The wrapper loader now records `__reactCompilerStatus__` events on **`module.buildInfo`** (not hashed) instead, and stores **paths relative to `rootContext`** rather than absolute filesystem paths. **`ReactCompilerPlugin`** reads and clears that key from `buildInfo` after emit; verbose reporting behavior is unchanged. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit b26ce25. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** - sticky table column headers - prevent status icon from shrinking ## **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** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Cosmetic layout and styling only; no logic, data, or security changes. > > **Overview** > Small UI polish for the cashtag token results table and overflow popover. > > The token results table header is now **sticky** (`sticky top-0` with background) so column labels stay visible while scrolling long result lists. The **24h volume** header uses `whitespace-nowrap` to avoid awkward wrapping, and the inline **security badge icon** gets `flex-shrink-0` so it doesn’t compress next to truncated tickers. > > **Overflow menu** popover panel adds `p-0` to strip default padding on the popover container. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 9b40a0b. 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 the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Interim while waiting for the new chart component, align color and line type with mobile ## **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** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> |before|after| |---|---| |<img width="375" height="720" alt="image" src="https://github.com/user-attachments/assets/12d409a6-d97f-421f-8e5a-e0b56208be0e" />|<img width="372" height="725" alt="image" src="https://github.com/user-attachments/assets/1bb8b68a-f65f-42f4-ba4e-31a94b236b2e" />| ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.
…46903) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> `submitRequestToBackground` allows UI files to call code defined within the "background" process. An engineer first defines a method within the object that `MetamaskController.getApi` returns. When `submitRequestToBackground` is called, the method and its arguments are passed to a persistent instance of `MetaRpcClient`. This object then sends a message through the background<->UI connection stream, and the message is processed on the background side. The background process ultimately calls a method on the `getApi` object. As time has gone on, we have encouraged engineers to place more logic inside of controllers and services instead of arbitrary locations within the background process. We have also integrated messengers across the stack. All controllers and services have messengers — little communication "devices" that can be used to enforce modularity — which are fed into a message bus, creating an application-wide "platform API". Provided that the proper wiring is in place, any UI file can access a controller or service through this message bus. We now consider the API defined by `getApi` to be legacy, and eventually, we want to migrate all instances of `submitRequestToBackground` to make use of the aforementioned message bus instead. Since this would take a long time, we are taking an intermediate route. In this commit, we change `submitRequestToBackground` so that if a UI messenger action type string is provided, the special `messengerCall` method in `getApi` is called, which routes the referenced action and its arguments through the message bus. (For instance, an engineer could pass `NetworkController:addNetwork` with its required arguments and it would end up calling `NetworkController.addNetwork`.) Gradually, we can convert all `submitRequestToBackground` callsites to use this new syntax and thus remove legacy methods from and finally deprecate `getApi`. ## **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** https://consensyssoftware.atlassian.net/browse/WPC-1290 ## **Manual testing steps** (N/A) ## **Screenshots/Recordings** (N/A) ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes the UI→background request entry point and uses a `:` heuristic to choose messenger vs legacy RPC; backward compatible but affects how all background calls are dispatched. > > **Overview** > **`submitRequestToBackground`** now accepts **root messenger action names** (e.g. `SnapController:installSnaps`) in addition to legacy background API method names. If the first argument contains `:`, the call is forwarded through the existing **`messengerCall`** RPC with the action name and argument list; otherwise behavior stays on the legacy **`background[method]`** path. > > Call sites get **stronger TypeScript typing** via `UIMessengerActions` and messenger `ExtractActionParameters` / `ExtractActionResponse`, including support for actions with all-optional parameters and no args. **Sentry trace context** is still appended when present, including for messenger-routed calls. > > **Tests** were added for messenger routing, default/optional args, trace propagation, and legacy method names (e.g. `messengerSubscribe`). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 490c9d2. 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 the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> Up to now, wiring UI code to the background so that it can call controllers and services was achieved by adding a method to the `MetamaskController.getApi` object. However, in recent months, the Core Platform team has developed an approach that can be shared between the Extension and Mobile codebases by taking advantage of the fact that controllers and services have messengers which feed into a "root messenger" (an application-wide API). For more information on this strategy, read here: https://github.com/MetaMask/core/blob/main/docs/legacy/ui-messengers-announcement.md We have been cleaning up bespoke infrastructure within MetamaskController into a LegacyBackgroundApiService, but both this class and `getApi` are now legacy code, and we do not want engineers to expand their surface area any longer. To enforce this, this commit: - Adds a JSON file, `legacy-background-api-snapshot.json`, which holds a snapshot of all members of `MetamaskController.getApi` and LegacyBackgroundApiService - Adds a new script, `development/legacy-background-api.ts`, which can be used to compare the current members to the snapshotted members to ensure that nothing new has been added (or to update the snapshot if it is out of date). - Adds a couple of new package scripts, `legacy-background:check` and `legacy-background:update`, and wires `legacy-background:check` into `lint` so that it is run on CI. ## **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/WPC-1294. ## **Manual testing steps** 1. Check out this branch. 2. Add a new method to `getApi` in `MetamaskController`. 3. Run `yarn legacy-background-api:check`. 4. You should see an error, recommending that this method be removed. 5. Add a new method to LegacyBackgroundApiService. 6. You should see an error (slightly different error message). 7. Remove the new methods and instead, modify `legacy-background-api-snapshot.json` by adding a new method under `MetamaskController.getApi`. 8. Run `yarn legacy-background-api:check`. 9. You should see a different error, recommending that the snapshot be updated. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> (N/A) ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Changes are limited to dev tooling, a snapshot file, and lint; runtime extension behavior is unchanged at merge time. > > **Overview** > Adds **snapshot-based enforcement** so `MetamaskController.getApi` and `LegacyBackgroundApiService` cannot grow without an intentional, Core Platform–reviewed update. > > A new `legacy-background-api-snapshot.json` records the allowed member names. The `development/legacy-background-api` CLI (`check` / `update`) parses those APIs from source (TypeScript AST), compares them to the snapshot, and fails with guidance toward UI messengers when new methods appear. `yarn legacy-background-api:check` is wired into `lint` (CI). **CODEOWNERS** assigns the snapshot and tooling to `@MetaMask/core-platform`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit a13d71a. 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 the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Clear release-blocking yarn audit advisories. - **`http-cache-semantics` ([GHSA-ch52-4w7c-c8xp](https://github.com/advisories/GHSA-ch52-4w7c-c8xp)):** Resolve to **4.3.0**. The `.yarnrc.yml` age-gate preapproval was removed after 7 Oct 2026. - **`braces` ([GHSA-vfj7-8cjw-p6xm](https://github.com/advisories/GHSA-vfj7-8cjw-p6xm)):** Resolve **`chokidar`** to **4.x** (the dashboard watch uses directory roots plus an extension filter, because Chokidar 4 does not expand globs); patch **`micromatch@4.0.8`** with the vendored depth-limit fix; resolve **`braces`** to **`npm-empty-package`**; add **`fill-range`** and a LavaMoat build-policy grant so patched micromatch can load it. - **`pbkdf2` → `^3.1.7`** for [GHSA-477h-4r7f-fvrx](GHSA-477h-4r7f-fvrx). - **`shell-quote` → `^1.11.0`** (lockfile **1.12.0**) for [GHSA-pqg4-j6r4-53mv](GHSA-pqg4-j6r4-53mv). - **`sharp` → `^0.35.5`** for [GHSA-wq5f-xc86-pv6w](GHSA-wq5f-xc86-pv6w). Additional production resolutions in the same lockfile: - **`postcss-selector-parser` 6.x → `^7.1.6`** for [GHSA-rj75-hqrm-r3gf](GHSA-rj75-hqrm-r3gf). This is a major bump; 7.1.6 keeps parse output byte-identical and only changes the flat-selector complexity. - **`compression` → `^1.8.2`** for [GHSA-vc2v-76pw-4v95](GHSA-vc2v-76pw-4v95). - **`proxy-addr` → `^2.0.8`** for [GHSA-jqcg-44mw-7w3h](GHSA-jqcg-44mw-7w3h). - **`source-map-js` → `^1.2.2`** for [GHSA-68fv-2mgg-jv7q](GHSA-68fv-2mgg-jv7q). - **`@grpc/grpc-js` → `^1.14.5`** for [GHSA-99f4-grh7-6pcq](GHSA-99f4-grh7-6pcq) (fixed in 1.14.4). <!-- 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: #46899 Fixes: #46883 Fixes: #46855 ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches crypto (`pbkdf2` / hashing) LavaMoat allowances and a major `postcss-selector-parser` resolution; risk is mitigated as audit-driven graph alignment rather than application logic changes. > > **Overview** > Clears release-blocking **yarn audit** findings by adding or tightening **Yarn resolutions** in `package.json` (notably **`postcss-selector-parser` 6.x → `^7.1.6`**, **`@grpc/grpc-js` → `^1.14.5`**, **`sharp` → `^0.35.5`**, plus bumps for GraphQL utils, tinypool, and OpenTelemetry instrumentation packages). The **`chokidar`** resolution line is removed from `resolutions` in this diff slice. > > **LavaMoat webpack policies** are updated to match the new lockfile graph. In **`lavamoat/webpack/build/policy.json`**, cssnano/tailwind consumers now allow a single **`stylelint>postcss-selector-parser`** dependency instead of many nested duplicate entries; **`webpack-dev-server>compression`** gains **`koa>destroy`**. > > Across **MV2/MV3** policy variants, **`crypto-browserify>pbkdf2`** no longer references separate **`pbkdf2>create-hash` / `pbkdf2>ripemd160`** subtrees—it routes through **`ethereumjs-util>create-hash`** instead. Related **`hash-base` / `readable-stream`** grants are expanded (e.g. **`@ngraveio/bc-ur>sha.js>to-buffer`**, dedicated safe-buffer/string_decoder nodes), and **`remote-redux-devtools>socketcluster-client>sc-channel`** now points at the nested **`sc-channel>component-emitter`** path. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit aa0004d. 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: MetaMask Bot <metamaskbot@users.noreply.github.com>
…x submission (#46872) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Alternative solution to [this PR](#46556) which introduced a new bug when importing multichain accounts. The new bug showed failed transactions on non-evm account import (if failed transactions on that account existed). On wallet start-up, non-evm historical account data is backfilled, so any existing failed transaction was added and then read as a transaction to be handled by the toast listener. As the code always showed a failed toast for a failed transaction, this led to the bug. This new solution adds a pre-submitted state for approved or signed transactions. It then allows failed transactions to be shown which were approved or signed but not submitted (e.g. the original nonce issue). But it doesn't create the non-evm bug as it still requires failed transactions to go through a pre-submitted state first. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Fixed a bug that hid the failed-transaction toast when a transaction failed before it was submitted ## **Related issues** Fixes: #46458 ## **Manual testing steps** Confirm that a send tx with a used/low nonce shows a failed toast Confirm that happy-path send still shows pending → success toasts Verify that rejecting on the confirmation screen still shows no toast ## **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/aa3af090-9983-48f3-b46a-087413181805 ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > UI-only toast gating with broad test coverage; behavior change is limited to when transaction notifications appear, not transaction handling. > > **Overview** > Introduces an **`approvedOrSigned` toast lifecycle phase** so transaction toasts only fire for txs the user actually started, fixing missing **failed** toasts when a send dies after approval/signing but before broadcast (e.g. nonce errors) without reintroducing spurious failed toasts for backfilled historical non-EVM failures. > > `setApprovedOrSignedToastPhase` is recorded on EVM `approved`/`signed` status updates; `shouldShowTerminalToast` now allows success/failure only after **approved/signed** or a shown **pending** toast, and `shouldShowPendingToast` no longer advances from unrelated phases. Hook tests cover approve→fail, approve→submit, reject, and historical/non-started failure paths for both controllers. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 47ede73. 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 the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Bump Snaps packages to latest, resolving a LavaMoat issue, uses the `cryptography` package and fixes some log statements. Due to type issues this PR also resolves `utils` to v12 across the board, the only breaking changes shipped are build-output and `engines` related so should have no impact on functionality. ## **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** https://consensyssoftware.atlassian.net/browse/WPC-1401 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches Snaps iframe execution URL and LavaMoat crypto/globals for all extension builds; utils v12 is a major bump but described as non-functional for consumers. > > **Overview** > Bumps **Snaps** stack and aligns shared **`@metamask/utils`** at **v12** across dependencies and Yarn resolutions. > > **Package / build config:** `@metamask/snaps-controllers` (21.1.2), `@metamask/snaps-utils` (12.6.1), `@metamask/snaps-execution-environments` (11.3.2), and `@metamask/utils` (12.0.0). All build flavors in `builds.yml` now point `IFRAME_EXECUTION_ENVIRONMENT_URL` at iframe **11.3.2**. > > **LavaMoat (MV2 policies for main/beta/experimental/flask):** Regenerated policies after dependency deduping—nested per-package `@metamask/utils` entries collapse to a single `@metamask/utils`; cryptography is wired through `@metamask/snaps-utils>@metamask/cryptography` (with `crypto.subtle.digest` allowed) instead of profile-sync’s copy; `@metamask/utils` no longer lists `@metamask/scure-bip39` in the policy. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 37174cd. 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: MetaMask Bot <metamaskbot@users.noreply.github.com>
## **Description** Adds a `TimestampEnforcer` deadline caveat to every EIP-7702 delegation, and moves delegation caveat generation into a dedicated `caveats.ts` module. - New `app/scripts/lib/transaction/caveats.ts` owns caveat building via `getDelegationCaveats`: - Provided caveats are used unchanged. - Otherwise shared base caveats (`limitedCalls`, deadline, and `redeemer` when redeemers are set) are combined with either `exactExecution` / `exactExecutionBatch` or the subsidized caveats. - New `app/scripts/lib/transaction/subsidized-caveats.ts` contains the subsidized `allowedTargets` / `allowedCalldata` logic, built from the parent execution. - Subsidized transactions reuse the default parent execution builder, and calldata normalization is private to `delegation.ts`. - The deadline defaults to 30 minutes and can be overridden with `deadlineSeconds` in the `confirmations_delegations` remote feature flag. - Adds dedicated unit tests for both modules. - `delegation.ts` now only orchestrates and imports the caveat helpers. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** 1. Submit a gas fee token transaction on an EIP-7702 supported network. 2. Verify the transaction is relayed and confirmed. 3. Submit a MetaMask Pay transaction and verify it completes. ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **High Risk** > Changes which caveats are signed into EIP-7702 delegations across gasless, sponsored, and relay paths; incorrect deadline or caveat ordering could break redemption or widen delegation scope. > > **Overview** > Adds a **TimestampEnforcer** deadline to every auto-generated EIP-7702 delegation and centralizes caveat construction in new modules. > > **`getDelegationCaveats`** (`caveats.ts`) now builds default caveats as `limitedCalls` → **timestamp** → optional `redeemer` → either `exactExecution` / `exactExecutionBatch` or subsidized `allowedTargets` / `allowedCalldata`. Caller-supplied `caveats` are returned as-is (no extra redeemer caveat). The expiry defaults to **30 minutes** and can be tuned via remote flag `confirmations_delegations.deadlineSeconds` (invalid values fall back to the default). > > **`delegation.ts`** delegates caveat generation to that helper, wires **`RemoteFeatureFlagController:getState`** on the delegation messenger, and moves subsidized calldata enforcement into **`subsidized-caveats.ts`** (without its own `LimitedCalls` caveat—limited calls live in the shared base). Publish/delegation tests expect **one additional caveat** (the timestamp) on relay flows. > > Registers `confirmations_delegations` in the e2e feature-flag registry and adds CI resolution for `CONFIRMATIONS_DELEGATIONS_FEATURE_FLAG_NAME`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 8252538. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** Non-Money MetaMask Pay deposits now prefill 50% of the selected token balance. Their transaction events also include the same amount-input metrics used by Money Account deposits. Prefill is enabled per transaction type by the `confirmations_pay_extended.prefilledAmount` flag, with no hard-coded type list, matching mobile. ## **Changelog** CHANGELOG entry: Updated Perps and Predict deposits to prefill half of the selected token balance. ## **Related issues** Fixes: CONF-2076 ## **Manual testing steps** 1. Start a Perps or Predict deposit with a funded token. 2. Open the MetaMask Pay confirmation. 3. Verify the amount is prefilled with 50% of the selected token balance. 4. Switch the selected token and verify the prefill updates to 50% of its balance. <!-- ## **Screenshots/Recordings** ### **Before** ### **After** --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes confirmation amount defaults, Max/prefill application, and Pay transaction metrics for multiple deposit types; incorrect prefill or Max arming could affect quoted/submitted amounts. > > **Overview** > Extends **MetaMask Pay deposit prefill** beyond money-account deposits: when `confirmations_pay_extended.prefilledAmount` is enabled per transaction type, Perps/Predict (and similar) confirmations prefilled **50%** of the selected token balance, while money-account deposits still use **100%** only for stablecoin route tokens (otherwise 50%). > > **`useDepositPrefillAmount`** is renamed to **`useDepositPrefill`** and now exposes **`percentage`** and **`isLimitCapped`** so consumers can apply percentage prefills vs fixed (limit-capped) amounts. **`useTransactionCustomAmount`** applies prefill whenever the hook is enabled (not only `moneyAccountDeposit`), routes 50%/uncapped-100% through **`updatePendingAmountPercentage`**, and avoids arming **`isMaxAmount`** for 100% prefills based on a stale snapshot balance. > > Amount-input analytics are centralized in **`useTransactionCustomAmountPercentageMetrics`** (`prefilled_50`, `prefilled_max`, `mm_pay_prefilled_amount`), replacing inline `upsertTransactionUIMetricsFragment` calls; executed transaction metrics continue to copy those UI fragment fields (e.g. perps deposits). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 649ae0e. 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 the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** PR #46742 changed the default Robinhood Chain block explorer to `https://robin.etherscan.io/`. That default is used when Robinhood Chain is added, but existing installations keep their previously persisted `NetworkController` configuration after an upgrade. As a result, users who already had Robinhood Chain configured continued to open `https://robinhoodchain.blockscout.com` unless they deleted and re-added the network. This PR adds state migration 231. For Robinhood Chain (`0x1237`), it replaces explorer entries whose hostname is exactly `robinhoodchain.blockscout.com` with `https://robin.etherscan.io/`. The migration preserves the explorer array order and `defaultBlockExplorerUrlIndex`, leaves custom and lookalike explorer URLs unchanged, and records `NetworkController` as changed so the migrated state is persisted. Unit tests cover the version bump, both trailing-slash forms of the old URL, index preservation, custom and lookalike URLs, missing network state, and migration registration. ## **Changelog** CHANGELOG entry: Fixed Robinhood Chain explorer links for existing users ## **Related issues** Refs: [WPN-2104](https://consensyssoftware.atlassian.net/browse/WPN-2104) Follow-up to #46742. ## **Manual testing steps** 1. Install Extension 13.51.0 in Chrome and complete onboarding. 2. Add Robinhood Chain and confirm its saved block explorer is `https://robinhoodchain.blockscout.com`. 3. Build this branch and update the same installed extension/profile without clearing its data. 4. Open an address or transaction explorer link while Robinhood Chain is selected. 5. Confirm the link opens on `https://robin.etherscan.io/` without deleting and re-adding the network. <!-- ## **Screenshots/Recordings** N/A — this is a persisted-state migration with no UI changes. --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [X] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [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. [WPN-2104]: https://consensyssoftware.atlassian.net/browse/WPN-2104?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Scoped persisted-state rewrite for one chain’s block explorer URLs with hostname-exact matching and broad test coverage; no auth or transaction logic changes. > > **Overview** > Adds **state migration 231** so existing installs pick up the Robinhood Chain block explorer change that new adds already get from defaults. > > On upgrade, if `NetworkController` has Robinhood Chain (`0x1237`), any `blockExplorerUrls` entry whose hostname is exactly `robinhoodchain.blockscout.com` is rewritten to `https://robin.etherscan.io/`. **Explorer list order** and **`defaultBlockExplorerUrlIndex`** stay the same; custom URLs and lookalike hostnames are untouched. When nothing matches or the chain isn’t configured, the migration is a no-op. Successful rewrites mark **`NetworkController`** as changed so persisted state updates. > > Migration **231** is wired into the migrations list, covered by unit tests (version bump, URL replacement, no-op cases), and e2e fixtures/snapshots bump **`meta.version`** / **`currentMigrationVersion`** from 230 to 231. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 07f1e8d. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** ### Context Native EVM sends calculated Max using a fixed 21,000 gas assumption. That assumption is not safe for networks or recipients where the selected RPC returns a higher gas requirement. ### Problem Selecting Max could fill the entire balance before a usable gas estimate was available, or reserve too little for the final transaction. On legacy and `eth_gasPrice` networks, Max reserved no gas at all because only the fee-market `medium.suggestedMaxFeePerGas` rate was read, so the confirmation was blocked with an insufficient-balance alert. Slow estimates could also race and overwrite newer results. ### Solution - Estimate the Max transaction with the node's `eth_estimateGas` on the send's network client, using the full raw balance as the value. Without fee fields, `eth_estimateGas` only requires the value to be covered by the balance. This was verified on mainnet, Arbitrum, Optimism, Base, Polygon, Linea, BSC and Scroll, where the estimate did not vary with value. - Reserve exactly `gasLimit × fee rate + L1 fee`, with no extra gas buffer. The fee rate is the same `medium` / `gasPrice` level TransactionController applies, and it supports fee-market, legacy and `eth_gasPrice` networks, reusing the GasFeeController estimate types. - Keep the background `estimateGas` as a plain `eth_estimateGas` request, only adding an optional `networkClientId`, so existing callers (subscription approval, edit spending cap) are unchanged. - Keep sponsored, token, and non-EVM sends on their existing full-balance behavior. - Keep Max stable as fee polling refreshes, while using the latest fee rate to calculate the amount. - Show loading only while estimation is running and show explanatory error copy only after estimation fails. - Prevent stale asynchronous estimates from replacing the latest result. ## **Changelog** CHANGELOG entry: Fixed native Max sends to reserve the gas estimated by the selected network. ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/CONF-1988 ## **Manual testing steps** 1. Build and load the extension, then fund an account with a native asset on an EVM network. 2. Start a native send and enter a valid recipient. 3. Verify the Max control shows a loading state while the gas estimate is being calculated. 4. Click Max after it becomes available and verify the amount is below the full balance by enough to reserve the estimated network fee. 5. Leave the send screen open through a gas-fee refresh and verify Max does not return to a loading or disabled state. 6. Continue to confirmation and verify the transaction can be submitted without an insufficient-funds error caused by gas. 7. Repeat with a balance close to the network fee and verify Max remains available when a smaller send amount is viable. 8. Repeat on a supported L2 and verify Max also reserves the displayed L1 fee. 9. Repeat on a legacy (non-EIP-1559) network, e.g. a local Anvil started with a pre-London hardfork, and verify Max reserves the network fee and the transaction can be submitted. 10. Configure an unreachable custom RPC, start another native send, and verify Max becomes disabled with an explanation after estimation fails. 11. On a gas-sponsored network, verify Max still selects the full native balance. ## **Automated testing** - `npx jest --no-watchman app/scripts/services/legacy-background-api-service.test.ts ui/hooks/useAsync.test.tsx ui/pages/confirmations/components/send/amount-recipient/amount-recipient.test.tsx ui/pages/confirmations/components/send/amount/amount.test.tsx ui/pages/confirmations/hooks/send/useMaxAmount.test.ts` - `npx jest --no-watchman ui/hooks/subscription ui/pages/confirmations/components/confirm/info/approve/edit-spending-cap-modal` - `yarn lint:tsc` - `yarn circular-deps:check` ## **Screenshots/Recordings** ### **Before** To be added before the PR is marked ready for review. ### **After** To be added before the PR is marked ready for review. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes how max native send amounts are computed across send and confirmation, which directly affects spendable value and fee reservation; regression risk is mitigated by updated hook tests but touches core transaction UX. > > **Overview** > **Moves native “Max” gas reservation off the send screen and into confirmation**, so the send flow no longer subtracts fees from a fixed 21k-gas / fee-estimate heuristic. > > `useMaxAmount` now returns the **full asset balance** (native, ERC20, Solana) and documents that native EVM gas is adjusted later by `useMaxValueRefresher` using `TransactionController` gas and fee fields. Related Redux/gas-estimate/L1-fee plumbing and `getLayer1GasFees` in send utils are removed, with tests narrowed to match. > > On confirmation, `useMaxValueRefresher` passes **`updateType: false`** when it writes the gas-adjusted value so a max send to a contract address stays classified as a simple send instead of flipping to a contract interaction. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 839b712. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** - Open the Chainlist network list with the add-network form, anchored under the network name field and filling the space above Save. Focusing or clicking Chain ID moves that list under the Chain ID field. - Keep the Add RPC suggestion list open for the chain being added. - Preserve in-progress form details when leaving and returning from Add RPC or Add block explorer. Return to Edit network when the block explorer page was opened from an existing network. - Allow any custom RPC URL to be deleted. Infura endpoints stay locked. - Rebuild the add block explorer page with the same design-system field, label, and footer as Add RPC. ## **Changelog** CHANGELOG entry: Fixed the add-network Chainlist lists so they stay open, stay attached to the field that opened them, and keep entered details when adding an RPC or block explorer URL. ## **Related issues** Fixes: ## **Manual testing steps** Enable the `extension-ux-chainlist-v-2` remote feature flag, then reload the extension. 1. Open Settings, then Networks, then Add custom network. 2. Confirm the Chainlist list is already open under Network name, matches that field's width, has no info icon in the source banner, and extends down the page. 3. Close the list, click Chain ID, and confirm the list opens under Chain ID rather than under Network name. 4. Pick a network that is not already added. Confirm the name, chain ID, ticker, and RPC stay filled in. 5. Open the RPC list and delete the custom RPC URL. Confirm it is removed. Repeat on an Infura network such as Ethereum and confirm that Infura endpoint cannot be deleted. 6. Fill the form again, open Add RPC URL, then press back. Confirm the name, chain ID, ticker, and RPC are still there and the Chainlist list does not cover them. 7. Open Add a block explorer URL, then press back. Confirm the same fields are still there. 8. On Add a block explorer URL, confirm the field and Add URL button match the Add RPC page. Enter an invalid URL and confirm the error appears. Enter a valid `https` URL and add it. 9. From Add custom network, pick a network that is already added so Edit network opens. Open Add a block explorer URL, then press back. Confirm you return to Edit network with that network's details, not to Add network. ## **Screenshots/Recordings** ### **Before** ### **After** https://github.com/user-attachments/assets/f3ddcd6d-c46e-45f9-a0ee-6b5335498ebb ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. Made with [Cursor](https://cursor.com) --------- Co-authored-by: Cursor <cursoragent@cursor.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This PR adds a CTA to token row. It will appear next to some stablecoins and vault tokens. The exact tokens it will appear next to is controlled by a feature flag. This PR adds two new flags. One to control which tokens the CTA appears next to, and another to control whether the CTA is shown at all. Both are essentially duplicates of the flags that we used in the mobile client. I have already set both flags up in launchdarkly <!-- 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: add money account CTAs to token row, gated behind feature flag ## **Related issues** Fixes: MUSD-1449 ## **Manual testing steps** 1. With the flags enabled (RC & Dev envs) visit the home page 2. Look at the token list, find a stablecoin for which you have balance 3. Observe the `get x% APY` CTA 4. Click it, you should see the deposit modal, prefilled with the appropriate token ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <img width="861" height="1287" alt="image" src="https://github.com/user-attachments/assets/ab1ec42c-c580-47db-8cb9-f5c00ddb5e8c" /> <!-- [screenshots/recordings] --> ### **After** https://github.com/user-attachments/assets/233452a0-4426-4984-b799-e8706d82fa61 <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Introduces a new deposit entry point on the home token list with remote flag and geo gating; mistakes could show CTAs or start deposits for wrong tokens, though parsing and eligibility fail closed. > > **Overview** > Adds a **feature-flagged “Get X% APY” CTA** on wallet token list rows for allowlisted ERC-20s, wired through new remote flags `earnMoneyTokenListItemCtaEnabled` and `earnMoneyDepositCtaTokenAddresses` (plus registry/i18n `moneyGetApy`). > > **`useMoneyTokenListCta`** resolves the CTA once per list (flags, geo/Money account, vault APY, min balance, blocked tokens); eligible rows render **`MoneyTokenListCta`**, which **replaces** the percent-change footer and **takes priority over** the mUSD convert link, then **tracks analytics** and **`initiateDeposit`** with the clicked token pre-selected. Vault APY fetching moves to **`useMoneyVaultApy`**; deposit eligibility is shared via **`getMoneyDepositFiatAmountUsd`**. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit bc2730c. 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 5.5 <noreply@anthropic.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Part 1/6 of the MFA phase 1 client kit (stacked PRs: #46909 → #46910 → #46911 → #46912 → #46913 → #46914; mobile stack starting at MetaMask/metamask-mobile#37234). The kit is not used by any feature yet, and its entry points are hidden in production builds. First piece of the MFA client kit on the extension: the platform-agnostic engine, a copy of metamask-mobile's (reviewed in MetaMask/metamask-mobile#37237). It talks to the controller through the ports in `engine/types.ts`. - `types.ts`: shared types (methods, plan steps, flow state, ports, kit error codes). - `planner.ts`: `getMethodStatuses` (a per-method view of the server's credential list) and the pure planners for `verifyOrEnroll` and `enroll`: what to set up, whether to confirm first, and whether a final verification is needed. - `errors.ts`: the error table that maps every MFA error code to how the flow handles it. **About the `eslint-disable` comments:** the engine is kept identical to metamask-mobile's (`app/util/identity/mfa/engine`) so both clients behave the same, and the two repos' lint rules disagree on a few points: mobile requires `interface` where the extension requires `type`, the error table's keys are the server's snake_case codes, and the SDK's WebAuthn types share their names with browser globals. Each disable is scoped to the lines concerned and says why. Nothing imports it yet. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** N/A: unit tests only; the code is not reachable from the UI yet. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> N/A ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > New, unused engine code with unit tests only; no runtime wiring yet, though the logic will eventually govern MFA enrollment and verification. > > **Overview** > Introduces the first slice of the extension MFA client kit under `ui/hooks/identity/mfa/engine`, aligned with metamask-mobile’s engine so both clients plan flows the same way. Nothing in the app imports it yet (stacked PR 1/6). > > **`types.ts`** defines shared contracts: credential method status, plan/flow steps and state, controller and passkey adapter ports, and kit-specific error codes. > > **`planner.ts`** adds pure planning for `verifyOrEnroll` and `enroll`—intro, confirm-before-enroll, setup order (with `verifyWith` methods last), session reuse/`maxSessionAgeMs`, platform limits (extension: email only; passkeys rejected until supported), and `getMethodStatuses` / `getEnrollmentMaxSessionAgeMs`. > > **`errors.ts`** maps every MFA flow error code to UI handling (`refresh`, `inline`, `restart`, etc.), normalizes unknown errors to `server_error`, and adds `MfaFlowError` for kit rejections. > > Unit tests cover the error table, planners, and edge cases (pending email, extension passkey rejection, session age rules). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 9d16de1. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
This PR is to update button text to Save in Add/edit contact and add tokens ## **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: null ## **Related issues** Fixes: Updating button save text. Going to update rest in follow up tickets https://consensyssoftware.atlassian.net/browse/CEUX-1401 ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <img width="1292" height="1590" alt="Screenshot 2026-10-12 at 5 07 52 PM" src="https://github.com/user-attachments/assets/19beaad7-3ddf-4ef2-80cb-878b5dc4bc88" /> <img width="1304" height="1606" alt="Screenshot 2026-10-12 at 5 09 37 PM" src="https://github.com/user-attachments/assets/b3085789-91f2-47e0-ba80-a8548feea623" /> <img width="1298" height="1562" alt="Screenshot 2026-10-12 at 5 09 59 PM" src="https://github.com/user-attachments/assets/85bc8637-5f19-4c00-aa04-2c233be51178" /> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Copy and layout-only UI changes; exit paths move to header navigation with no backend or persistence logic changes. > > **Overview** > **Aligns primary action copy and contact form footers** with a single **Save** label on add/edit contact and custom token import (replacing **Add token** on import). > > On **add** and **edit contact**, the footer **Cancel** button and `onCancel` wiring are removed; dismissal is via the page header **back** / **close** controls. The **Save** action is **full width** in the footer instead of sharing a row with Cancel. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 49e2c43. 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 the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Part 2/6 of the MFA phase 1 client kit (stacked PRs: #46909 → #46910 → #46911 → #46912 → #46913 → #46914; mobile stack starting at MetaMask/metamask-mobile#37234). The kit is not used by any feature yet, and its entry points are hidden in production builds. The engine's runtime, a copy of metamask-mobile's (reviewed in MetaMask/metamask-mobile#37238): - `flow.ts`: `createMfaFlow`, a state machine (`getState` / `subscribe` / `dispatch`) that runs the plan step by step, re-plans from fresh state after each step and applies the error table. - `activeFlow.ts`: one MFA flow at a time; an identical request joins the running flow, anything else gets `flow_in_progress`. - `useActiveMfaFlow.ts`: a `useSyncExternalStore` hook for the page that hosts a flow. The `eslint-disable` comments are explained in the previous PR of the stack. Nothing imports it yet. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** N/A: unit tests only; the code is not reachable from the UI yet. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> N/A ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > New, test-only MFA kit code with no production imports yet; behavior mirrors the reviewed mobile engine and does not change existing auth paths. > > **Overview** > Adds the **MFA engine runtime** (part 2 of the phase 1 client kit): orchestration and UI-facing state, still **not wired into any feature**. > > **`createMfaFlow`** (`flow.ts`) is a dispatch-driven state machine that advances through planner steps (intro, email entry, OTP, passkey, method picker, success/failure), talks to the MFA controller adapter for enroll/verify, and maps SDK errors to inline retry, cooldown, credential refresh, or terminal failure. It can finish silently when credentials and a valid session already satisfy the request. > > **`startMfaFlow`** (`activeFlow.ts`) enforces a **single global flow**: identical operation + request joins the in-flight promise; anything else rejects with `flow_in_progress`, and the slot clears when the flow settles. > > **`useActiveMfaFlow`** exposes the active flow and live `MfaFlowState` to React via `useSyncExternalStore`. > > Broad unit coverage is included for flow behavior, singleton semantics, and the hook. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 5afeeca. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Builds ready [acf000d]
⚡ Performance Benchmarks (Total: 🟢 8 pass · 🟡 3 warn · 🔴 2 fail)
Bundle Size Diffs [🚨 Warning! Bundle size has increased!]
Cherry-picks (9 commits)
Changelog (107 commits since v13.53.0)
AI Test Plan
Cherry-Pick Scenarios (3)Medium Risk Scenarios (3)1. Snaps: Tron Snap update (connect, sign transaction, permissions)Risk Level: MEDIUM Why This Matters: Cherry-pick 47122 bumps Tron Snap; Snap permission/signing flows can break on version changes, risking failed sends or incorrect confirmations. Test Steps:
2. Snaps: Solana Snap update (connect, sign, message signing)Risk Level: MEDIUM Why This Matters: Cherry-pick 47122 updates Solana Snap; changes may affect signing formats and account routing, causing user-facing errors. Test Steps:
3. Snaps: Stellar Wallet Snap update (connect, sign transaction)Risk Level: MEDIUM Why This Matters: Cherry-pick 47224 updates the Stellar Snap; permission and signing behavior can change with Snap versions and must be validated. Test Steps:
Release Scenarios (10)High Risk Scenarios (6)1. State Migrations (231–233): NFT detection and asset preferencesRisk Level: HIGH Why This Matters: Migrations can inadvertently drop or duplicate user assets; manual NFT imports and detection settings are persistent user data that must not regress. Test Steps:
2. State Migrations (231–233): Network enablement and asset fetch behaviorRisk Level: HIGH Why This Matters: Network enablement logic impacts background asset fetching; incorrect defaults or migrations can cause unexpected RPC traffic or missing tokens. Test Steps:
3. Transaction Sending: EIP-1559 fee estimation and speed-up/cancel (Transaction Pay Controller patch)Risk Level: HIGH Why This Matters: A patched transaction-pay dependency can break fee estimation or replacement logic, causing user loss or stuck transactions. Test Steps:
4. Transaction Sending: Legacy gas on non-1559 networksRisk Level: HIGH Why This Matters: Incorrect handling of legacy gas can block transactions on popular non-1559 networks, directly impacting user funds. Test Steps:
5. Assets: Network enablement initialization (Assets/network-enablement-controller-init)Risk Level: HIGH Why This Matters: Initialization changes can cause missing or excessive asset fetches per network, impacting performance and user trust in balances. Test Steps:
6. NFTs: Detection notice and Import NFTs flowRisk Level: HIGH Why This Matters: New notice/UI around NFT detection can alter the import flow; errors here create duplicates or hide assets. Test Steps:
Medium Risk Scenarios (4)1. Account Group Balance: Totals and currency conversion accuracyRisk Level: MEDIUM Why This Matters: A miscalculated group balance undermines user trust and can drive incorrect financial decisions. Test Steps:
2. Privacy and Analytics: MetaMetrics consent and event gatingRisk Level: MEDIUM Why This Matters: Analytics adapter changes can inadvertently enable tracking when disabled or destabilize flows guarded by analytics checks. Test Steps:
3. App State Controller: Lock/Unlock and pending approvals UXRisk Level: MEDIUM Why This Matters: App-state changes can cause lost approvals or broken navigation, directly affecting signing and dapp trust. Test Steps:
4. Assets List Interaction: Search/filter stabilityRisk Level: MEDIUM Why This Matters: UI changes in the assets list/control bar can introduce subtle state bugs affecting token discoverability. Test Steps:
Teams Sign-off StatusSigned off: None yet Awaiting sign-off (9): Generated by AI Test Plan Analyzer (gpt-5) at 2026-10-23T03:15:51.297Z AI generated test plan (JSON): test-plan-13.54.0.json |
- fix(ui): bottom navbar cp-13.54.0 cp-13.55.0 (#47321) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Money routes can be a dead-end if reached without the bottom navbar The bottom navbar is dependent on LaunchDarkly and if unavailable can cause the dead-end scenario above Since bottom navbar has been resolved to treatment in the latest main branch, retroactively applying it to older versions to avoid the issue above ## **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: enable bottom navbar ## **Related issues** https://consensys.slack.com/archives/C06FXU326RL/p1792765914662259 Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes default UX for one AB test when flags are missing or invalid, which affects navigation on money routes but is limited to non-test runtime and preserves explicit flag assignments. > > **Overview** > When LaunchDarkly does not yield a valid bottom-nav AB assignment, **`resolveABTestAssignment`** now falls back to **`treatment`** (bottom navbar on) instead of **`control`**, matching the resolved behavior on latest main and avoiding money flows that become a dead end without the navbar. > > The special-case applies only for **`BOTTOM_NAV_AB_TEST_KEY`** and is skipped when **`IN_TEST`** or **`NODE_ENV === 'test'`**, so other AB tests still default to **`control`** and unit tests keep the prior behavior. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit d58b39a. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> [b094138](b094138) Co-authored-by: Francis Nepomuceno <n3ps@users.noreply.github.com>
Builds ready [3755e33]
⚡ Performance Benchmarks (Total: 🟢 7 pass · 🟡 3 warn · 🔴 3 fail)
Bundle Size Diffs [🚨 Warning! Bundle size has increased!]
Cherry-picks (10 commits)
Changelog (108 commits since v13.53.0)
AI Test Plan
Cherry-Pick Scenarios (3)Medium Risk Scenarios (3)1. Snaps: Tron and Solana snap bumpsRisk Level: MEDIUM Why This Matters: Cherry-pick 47122 bumps chain snaps that can alter permissions and signing flows; regressions here can break cross-chain interactions and user security prompts. Test Steps:
2. Snaps: Stellar Wallet Snap bumpRisk Level: MEDIUM Why This Matters: Cherry-pick 47224 updates the Stellar Wallet Snap; version bumps can change permission scopes and signing behavior, risking broken or unsafe user prompts. Test Steps:
3. UI Navigation: Bottom Navbar fixRisk Level: MEDIUM Why This Matters: Cherry-pick 47322 fixes bottom navbar behavior; navigation regressions can strand users or hide critical actions across core app areas. Test Steps:
Release Scenarios (11)High Risk Scenarios (5)1. State Migrations (231–233) — existing usersRisk Level: HIGH Why This Matters: Migrations can corrupt or reset persisted user state; three new migrations in one release increase the chance of data loss or inconsistent settings across networks and assets. Test Steps:
2. State Migrations (231–233) — locked vault/first-unlock pathRisk Level: HIGH Why This Matters: Some migrations run pre- or post-unlock; running them against encrypted state can lead to partial migrations or blank UI until a refresh. Test Steps:
3. Transaction Creation and Gas Controls (Transaction Pay Controller patch)Risk Level: HIGH Why This Matters: Controller patching around transaction payment introduces risk to gas estimation, EIP-1559 handling, and replacement transactions—core functions that must not regress. Test Steps:
4. Network Enablement Initialization (network-enablement-controller-init)Risk Level: HIGH Why This Matters: Initialization changes can misconfigure which networks appear or are enabled, breaking core flows like switching networks or adding tokens. Test Steps:
5. Assets Initialization and Detection (assets-controller-init)Risk Level: HIGH Why This Matters: Controller/init changes can lead to duplicate tokens, cross-network leakage of assets, or incorrect persistence of visibility settings. Test Steps:
Medium Risk Scenarios (6)1. NFT Empty State and Detection NoticeRisk Level: MEDIUM Why This Matters: New notices and empty-state logic can confuse users or lead to duplicates/missing NFTs if detection vs manual import states are mishandled. Test Steps:
2. Account Group Balance displayRisk Level: MEDIUM Why This Matters: Incorrect aggregation or formatting can mislead users about portfolio value and undermine trust. Test Steps:
3. Asset List Control Bar (filters/search/sorting)Risk Level: MEDIUM Why This Matters: Small control-bar regressions can block discoverability of assets or lead to incorrect list states across networks. Test Steps:
4. Onboarding, App State, and Analytics Consent (app-state-controller, analytics platform-adapter)Risk Level: MEDIUM Why This Matters: Changes to app-state and analytics wiring can cause repeat prompts, lost preferences, or degraded first-run UX. Test Steps:
5. Network switching across Tokens/NFTs/Activity tabsRisk Level: MEDIUM Why This Matters: Controller/init refactors often surface as cross-tab stale data or incorrect network scoping. Test Steps:
6. Speed Up/Cancel flows across networksRisk Level: MEDIUM Why This Matters: Any transaction controller changes can cascade into replacement-transaction handling and surface as stuck or duplicated entries. Test Steps:
Teams Sign-off StatusSigned off: None yet Awaiting sign-off (7): Generated by AI Test Plan Analyzer (gpt-5) at 2026-10-23T19:22:21.007Z AI generated test plan (JSON): test-plan-13.54.0.json |
Builds ready [0801fdb]
⚡ Performance Benchmarks (Total: 🟢 6 pass · 🟡 5 warn · 🔴 2 fail)
Bundle Size Diffs [🚨 Warning! Bundle size has increased!]
Cherry-picks (11 commits)
Changelog (109 commits since v13.53.0)
AI Test Plan
Cherry-Pick Scenarios (3)High Risk Scenarios (2)1. Snaps — Solana transaction signing and permissionsRisk Level: HIGH Why This Matters: Cherry-pick 47122 bumps the Solana Snap; Snap permission/transaction changes can break account derivation and signing, directly impacting user funds and dApp compatibility. Test Steps:
2. Snaps — Tron transaction signing and account managementRisk Level: HIGH Why This Matters: Cherry-pick 47122 bumps the Tron Snap; any signing or address-derivation regression will block Tron dApp usage and risk failed transactions. Test Steps:
Medium Risk Scenarios (1)1. UI Navigation — bottom navbar responsiveness and visibilityRisk Level: MEDIUM Why This Matters: Cherry-pick 47322 fixes bottom navbar issues; navigation is core to usability in the popup, and regressions can block users from reaching key screens. Test Steps:
Release Scenarios (13)High Risk Scenarios (6)1. State Migrations (231–233) — data preservationRisk Level: HIGH Why This Matters: Migrations can silently corrupt or drop user state; validating end-to-end preservation avoids asset loss, wrong balances, and broken preferences after upgrade. Test Steps:
2. State Migrations (231–233) — resilience to partial/corrupt stateRisk Level: HIGH Why This Matters: Defensive migrations must handle missing or malformed data to prevent bricked UIs and user lockouts. Test Steps:
3. Transaction Flow — EIP-1559 gas editing, speed up/cancel (Transaction Pay Controller patch)Risk Level: HIGH Why This Matters: Core transaction payment logic changes can break fee calculations and nonce management, risking stuck transactions or user overpayment. Test Steps:
4. Transaction Flow — token approvals and swaps fee estimationRisk Level: HIGH Why This Matters: Approvals and swaps are high-frequency flows; mis-estimated or misapplied fees can cause failed txns, stuck approvals, or financial loss. Test Steps:
5. Network Enablement Gating — Buy/Swap/Bridge feature visibility per networkRisk Level: HIGH Why This Matters: Incorrect feature gating confuses users and can route them to broken flows or unsupported services. Test Steps:
6. Assets Controller Initialization — first-run defaults and token detectionRisk Level: HIGH Why This Matters: Initialization regressions can cause missing or duplicate assets, leading to user distrust and support incidents. Test Steps:
Medium Risk Scenarios (7)1. NFTs — detection notice and manual import flowRisk Level: MEDIUM Why This Matters: Users rely on clear guidance when NFTs aren’t auto-detected; incorrect notices or duplication undermine confidence. Test Steps:
2. NFTs — empty state behavior across networksRisk Level: MEDIUM Why This Matters: Accurate empty states prevent user confusion and encourage correct next actions (import, detection). Test Steps:
3. Account Group Balance — aggregate fiat/native displayRisk Level: MEDIUM Why This Matters: Incorrect totals or formatting can mislead users about their portfolio value and cause financial mistakes. Test Steps:
4. App State — lock/unlock, routing, and recovery from interruptsRisk Level: MEDIUM Why This Matters: App-state regressions trap users on wrong routes or overlays, breaking core wallet usability. Test Steps:
5. Analytics opt-in/out — preference, persistence, and behaviorRisk Level: MEDIUM Why This Matters: Privacy controls must be trustworthy; unexpected telemetry erodes user trust and may have compliance implications. Test Steps:
6. Asset List Control Bar — sorting/filter persistenceRisk Level: MEDIUM Why This Matters: Small UI regressions in high-traffic lists quickly degrade usability and accessibility. Test Steps:
7. Online/Offline initialization — controller rehydrationRisk Level: MEDIUM Why This Matters: Robust initialization must handle connectivity changes; failures here cause blank screens or stale balances. Test Steps:
Teams Sign-off StatusSigned off: None yet Awaiting sign-off (9): Generated by AI Test Plan Analyzer (gpt-5) at 2026-10-24T00:53:06.063Z AI generated test plan (JSON): test-plan-13.54.0.json |
…ci, serialize-javascript, and GridPlus zod cp-13.54.0 (#47358) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** New production advisories were blocking release. Same-major patches: - `fast-uri` 3.1.8 → 3.1.9 - `body-parser` 1.20.6 → 1.20.9 and 2.3.0 → 2.4.0 - `undici` 7.30.0 → 7.30.1 - `serialize-javascript` 7.0.5 → 7.1.3 - Zod 4 ranges, including `gridplus-sdk`'s `^4.1.11`, re-resolved to 4.6.7 with no resolution The snap copies are an exact pin at 3.25.76, so those two use a resolution to `^4.6.6`. The snap bundles do not import Zod. `@reown/appkit-wallet` stays on Zod 3.22.4, which is dev-only. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Same-major dependency and resolution-only changes driven by advisories; no extension logic or API surface changes in the diff. > > **Overview** > Bumps **Yarn resolutions** and the lockfile so production security advisories can clear for release 13.54.0. No application source changes. > > **Pinned / resolution updates in `package.json`:** `serialize-javascript` **7.0.5 → 7.1.3**, `undici` **^7.30.0 → ^7.30.1**, `fast-uri` **^3.1.8 → ^3.1.9**, and explicit **zod 4.6.7** for `@metamask/gator-permissions-snap` and `@metamask/permissions-kernel-snap` nested dependencies (those snaps ship an older zod copy that does not affect runtime validation in the extension). > > **Lockfile fallout:** `body-parser` **1.20.9** and **2.4.0** (with `qs` ~6.16), plus minor transitive bumps (`content-type` 2.1.0, `iconv-lite` 0.7.3). Shared **zod** v4 ranges resolve to **4.6.7** (from 4.6.5); the standalone **3.25.76** lock entry is folded into the v4 resolution set per the PR notes. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit b93aca1. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…ci, serialize-javascript, and GridPlus zod (#47363) - chore: patch fast-uri, body-parser, undici, serialize-javascript, and GridPlus zod cp-13.54.0 (#47358) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** New production advisories were blocking release. Same-major patches: - `fast-uri` 3.1.8 → 3.1.9 - `body-parser` 1.20.6 → 1.20.9 and 2.3.0 → 2.4.0 - `undici` 7.30.0 → 7.30.1 - `serialize-javascript` 7.0.5 → 7.1.3 - Zod 4 ranges, including `gridplus-sdk`'s `^4.1.11`, re-resolved to 4.6.7 with no resolution The snap copies are an exact pin at 3.25.76, so those two use a resolution to `^4.6.6`. The snap bundles do not import Zod. `@reown/appkit-wallet` stays on Zod 3.22.4, which is dev-only. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Same-major dependency and resolution-only changes driven by advisories; no extension logic or API surface changes in the diff. > > **Overview** > Bumps **Yarn resolutions** and the lockfile so production security advisories can clear for release 13.54.0. No application source changes. > > **Pinned / resolution updates in `package.json`:** `serialize-javascript` **7.0.5 → 7.1.3**, `undici` **^7.30.0 → ^7.30.1**, `fast-uri` **^3.1.8 → ^3.1.9**, and explicit **zod 4.6.7** for `@metamask/gator-permissions-snap` and `@metamask/permissions-kernel-snap` nested dependencies (those snaps ship an older zod copy that does not affect runtime validation in the extension). > > **Lockfile fallout:** `body-parser` **1.20.9** and **2.4.0** (with `qs` ~6.16), plus minor transitive bumps (`content-type` 2.1.0, `iconv-lite` 0.7.3). Shared **zod** v4 ranges resolve to **4.6.7** (from 4.6.5); the standalone **3.25.76** lock entry is folded into the v4 resolution set per the PR notes. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit b93aca1. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> [396c3f1](396c3f1) --------- Co-authored-by: Danica Shen <zhaodanica@gmail.com> Co-authored-by: metamask-ci[bot] <271559518+metamask-ci[bot]@users.noreply.github.com>
Builds ready [799dbd7]
⚡ Performance Benchmarks (Total: 🟢 10 pass · 🟡 1 warn · 🔴 2 fail)
Bundle Size Diffs [🚨 Warning! Bundle size has increased!]
Cherry-picks (14 commits)
Changelog (112 commits since v13.53.0)
AI Test Plan
Cherry-Pick Scenarios (2)High Risk Scenarios (1)1. Snaps: Tron and Solana Snap version bumpRisk Level: HIGH Why This Matters: Cherry-pick 47122 updates Tron and Solana Snaps, which can alter permissions, account derivation, and signing/transaction behavior; regressions here would break non-EVM user flows. Test Steps:
Medium Risk Scenarios (1)1. Navigation: Bottom navbar behaviorRisk Level: MEDIUM Why This Matters: Cherry-pick 47322 fixes bottom navbar issues that can block navigation or approvals, directly impacting core user flows. Test Steps:
Release Scenarios (10)High Risk Scenarios (6)1. State Migrations (231): Asset/Network enablement and settings reshapingRisk Level: HIGH Why This Matters: Migrations can corrupt or drop persisted data; this ensures asset visibility, detection settings, and network enablement map correctly to the new schema without user data loss. Test Steps:
2. State Migrations (232): NFT detection and import flowRisk Level: HIGH Why This Matters: Migration changes around NFT detection/notice can confuse users or misrepresent detection state, risking missed assets or duplicate imports. Test Steps:
3. State Migrations (233): App-state persistence (dismissed banners, onboarding, preferences)Risk Level: HIGH Why This Matters: App-state migrations can regress preferences and UI flags, causing spammy banners, lost settings, or broken approval flows. Test Steps:
4. Transaction Flow: Transaction Pay Controller patchRisk Level: HIGH Why This Matters: A patched transaction-pay controller directly affects fee calculation, submission, and replacement flows; regressions here can cause stuck or mispriced transactions. Test Steps:
5. Network Management: Network Enablement Controller initializationRisk Level: HIGH Why This Matters: Reworked controller init can flip defaults or break persistence, impacting which networks and assets users can see or use. Test Steps:
6. Security: Message/HTML sanitization in signing and insights surfacesRisk Level: HIGH Why This Matters: Sanitizer/library patches can create XSS risks in approval UIs, leading to phishing or UI hijacking at critical signing moments. Test Steps:
Medium Risk Scenarios (4)1. Approvals and Session Restore: App State Controller changesRisk Level: MEDIUM Why This Matters: Changes to app-state controller can disrupt approval continuity, causing lost context or stuck approvals. Test Steps:
2. Portfolio Display: Account Group Balance calculationRisk Level: MEDIUM Why This Matters: Incorrect balance aggregation erodes trust and can influence send/receive decisions. Test Steps:
3. NFTs: Detection notice and manual import pathwayRisk Level: MEDIUM Why This Matters: Reworked notice and flow must correctly guide users between manual import and detection, avoiding duplicates or missing items. Test Steps:
4. Assets List: Control bar search/filter behaviorRisk Level: MEDIUM Why This Matters: Small logic changes in list controls can degrade asset discovery and lead to user confusion. Test Steps:
Teams Sign-off StatusSigned off: None yet Awaiting sign-off (9): Generated by AI Test Plan Analyzer (gpt-5) at 2026-10-26T19:38:53.622Z AI generated test plan (JSON): test-plan-13.54.0.json |
There was a problem hiding this comment.
Client UI review (modern-web-guidance)
Two new Money surfaces use clickable containers that wrap real buttons/links. That creates nested interactive elements and leaves keyboard/screen-reader users with ambiguous targets (modern-web-guidance accessibility: prefer native <button>/<a> and avoid nesting interactives).
No Chrome extension / MV3 issues stood out in this release diff (app/ changes are controller wiring, cashtag selector tweaks, and E2E wallet-init).
Sent by Cursor Automation: Modern web guidance
| marginHorizontal={4} | ||
| marginTop={4} | ||
| className="cursor-pointer rounded-xl" | ||
| onClick={onBannerClick} |
There was a problem hiding this comment.
Nested interactives / non-native banner control: The outer Box is clickable (onClick={onBannerClick}) but it is not keyboard-focusable and has no role/tabIndex/onKeyDown. It also wraps a dismiss ButtonIcon and a TextButton CTA, so assistive tech sees buttons inside another activation target.
Suggestion: Pick one primary action pattern—for example, make only the CTA a <button> (and keep dismiss separate), or use a single native <button type="button"> for the banner body and drop the outer onClick. If the whole row must navigate, avoid nesting: put dismiss/CTA outside the banner button or use stopPropagation on siblings without making the parent a pseudo-control. Match the keyboard pattern used in money-account-balance (role="link", tabIndex={0}, Enter/Space handler) if you keep a non-button wrapper.
| alignItems={BoxAlignItems.Center} | ||
| padding={4} | ||
| className="cursor-pointer rounded-r-2xl" | ||
| onClick={startDeposit} |
There was a problem hiding this comment.
Nested interactives on the Add section: This Box calls onClick={startDeposit} while the child Add component renders a design-system Button with its own onClick. That duplicates activation and nests interactive elements (section click + button), which is awkward for keyboard and screen-reader users.
Suggestion: Keep a single control—either remove the wrapper onClick and enlarge the Button hit area with padding/className, or replace the inner Button with non-interactive styling and put role="button", tabIndex={0}, and Enter/Space handling on the section (same pattern as the summary block above).
Builds ready [4bb70a9]
⚡ Performance Benchmarks (Total: 🟢 6 pass · 🟡 5 warn · 🔴 2 fail)
Bundle Size Diffs [🚨 Warning! Bundle size has increased!]
Cherry-picks (15 commits)
Changelog (113 commits since v13.53.0)
AI Test Plan
Cherry-Pick Scenarios (4)Medium Risk Scenarios (4)1. Snaps — Tron Snap bump (install/connect and sign flow)Risk Level: MEDIUM Why This Matters: Cherry-pick 47122 updates critical Snap behavior; Snap bumps can change permissions, key derivation, or signing flows causing broken connections or failed approvals. Test Steps:
2. Snaps — Solana Snap bump (install/connect and sign flow)Risk Level: MEDIUM Why This Matters: Cherry-pick 47122 updates Solana Snap; changes can impact signing UX, address formats, or permission prompts, breaking dapp interoperability. Test Steps:
3. Snaps — Stellar Wallet Snap bump (basic install and send)Risk Level: MEDIUM Why This Matters: Cherry-pick 47224 updates Stellar Snap; Snap upgrades can subtly break address derivation and signing or introduce new permission scopes. Test Steps:
4. UI Navigation — bottom navbar fixRisk Level: MEDIUM Why This Matters: Cherry-pick 47322 fixes navigation; navbar regressions can block critical actions or obscure confirmations on small viewports. Test Steps:
Release Scenarios (10)High Risk Scenarios (4)1. State Migrations (231–233) — assets/network enablement flags and UI gatingRisk Level: HIGH Why This Matters: Migrations can corrupt or reset user preferences and asset lists; verifying preserved settings and clean UI state prevents asset loss confusion and broken onboarding prompts. Test Steps:
2. Network Enablement Controller Init — first-visit prompts and per-network defaultsRisk Level: HIGH Why This Matters: Initialization order and persistence of per-network enablement can cause repeated prompts or incorrect defaults, disrupting users and creating inconsistent detection behavior. Test Steps:
3. Assets Controller Init — token detection and deduplicationRisk Level: HIGH Why This Matters: Controller init refactors can introduce race conditions or duplication in asset discovery, affecting balances and user trust. Test Steps:
4. NFT Import Flow — Detection Notice on 'Import NFTs'Risk Level: HIGH Why This Matters: A new notice in a critical flow can block or confuse NFT imports, causing users to miss assets or repeat actions. Test Steps:
Medium Risk Scenarios (6)1. NFTs Empty State — copy/CTA behavior with detection on/offRisk Level: MEDIUM Why This Matters: Incorrect empty-state guidance can mislead users about how to add or discover NFTs, increasing support burden. Test Steps:
2. Account Group Balance — total computation and hidden assetsRisk Level: MEDIUM Why This Matters: Balance integrity drives user trust; UI refactors can miscompute totals, especially with hidden assets and pending transactions. Test Steps:
3. Assets List Control Bar — search/filter/sort stabilityRisk Level: MEDIUM Why This Matters: Small control-bar changes can regress filtering or persistence, making it hard to locate assets. Test Steps:
4. App State Controller — lock/unlock and modal/popup persistenceRisk Level: MEDIUM Why This Matters: App-state bugs around lock/unlock can strand users mid-flow or re-show dismissed UI elements, breaking critical journeys. Test Steps:
5. Analytics Platform Adapter — consent-gated eventsRisk Level: MEDIUM Why This Matters: Privacy and regulatory expectations require strict consent gating; adapter changes can accidentally emit events without consent. Test Steps:
6. Send Transaction — gas estimate and confirmation (regression around transaction-pay controller patch)Risk Level: MEDIUM Why This Matters: Low-level controller patches can impact gas estimation or fee flows; regressions here directly cause failed or overpriced transactions. Test Steps:
Teams Sign-off StatusSigned off: None yet Awaiting sign-off (7): Generated by AI Test Plan Analyzer (gpt-5) at 2026-10-27T02:54:04.449Z AI generated test plan (JSON): test-plan-13.54.0.json |


🚀 v13.54.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