release: 13.42.0#44797
Conversation
…44294) Fixes: https://github.com/MetaMask/MetaMask-planning/issues/7466 CHANGELOG entry: null Derived values from multiple `useSelector` calls in the home balance hot path were recomputed on every render, even when their dependencies hadn't changed. ### Changes - **`aggregated-balance.tsx`** — memoize `showNativeTokenAsMain`, `isNonEvmRatesAvailable`, `formattedFiatDisplay`, `formattedTokenDisplay` - **`coin-overview.tsx` (`LegacyAggregatedBalance`)** — memoize `showNativeTokenAsMain`, `isNotAggregatedFiatBalance`, `balanceToDisplay`; convert `getCurrencyDisplayType()` inline function to `useMemo` - **`coin-overview.tsx` (`CoinOverview`)** — memoize `isMetaMetricsEnabled`, `shouldShowBalanceEmptyState`; wrap `handleSensitiveToggle` in `useCallback` - **`aggregated-percentage-overview.tsx`** — consolidate all derived display values (`amountChange`, `percentageChange`, formatted strings, `color`) into a single `useMemo` in both `AggregatedPercentageOverview` and `AggregatedMultichainPercentageOverview` - **`aggregated-percentage-overview-cross-chains.tsx`** — wrap `getPerChainTotalFiat1dAgo` (closes over `crossChainMarketData`) in `useCallback`; consolidate derived cross-chain display values into a single `useMemo` - **`account-group-balance.tsx`** — memoize `caipChainId`, `isEvm`, `isTestnetSelected`, `showNativeTokenAsMain` ### Example ```tsx // Before: recomputed on every render const showNativeTokenAsMain = showNativeTokenAsMainBalance && Object.keys(enabledNetworks).length === 1; // After: only recomputed when deps change const showNativeTokenAsMain = useMemo( () => showNativeTokenAsMainBalance && Object.keys(enabledNetworks).length === 1, [showNativeTokenAsMainBalance, enabledNetworks], ); ``` <!-- CURSOR_SUMMARY --> --- > [!NOTE] > <sup>[Cursor Bugbot](https://cursor.com/bugbot) is generating a summary for commit c8ad878. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: dddddanica <zhaodanica@gmail.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 completes the **"Sync with mobile"** flow in MetaMask Extension.
After pairing with MetaMask Mobile via QR code, the extension sends the
user's selected wallets and accounts to mobile in a secure, structured
format.
The extension is the **sender**; mobile is the **receiver**.
### What changed
- Built the full **wallet export payload** sent when sync is ready
(`sync-ready` message).
- Users pick which wallets to sync (SRP wallets and imported private-key
accounts only — hardware and Snap wallets are excluded).
- Account names, primary wallet flag, and hidden/pinned states are
included so mobile can restore the same setup.
- Added `QrSyncDataService` to build the export payload from the user's
account selection.
- Wired the Settings UI through to the controller end-to-end.
### Flow by phase
Each step shows what the **user sees (UI)**, what the **extension does
behind the scenes (Controller)**, and what **MetaMask Mobile** does.
They communicate through a secure relay (MWP).
---
#### Phase 1: `idle` → `displaying-qr` — Start pairing
```
User opens "Sync with mobile"
│
▼
┌─────────────┐ create session ┌──────────────┐
│ UI │ ───────────────────► │ Controller │
│ (QR code) │ ◄─────────────────── │ │
└─────────────┘ show QR code └──────┬───────┘
│
│ init-sync-session
▼
┌──────────────┐
│ Mobile │
│ (scans QR) │
└──────────────┘
```
**What happens:** User opens Settings → Sync with mobile. The extension
creates a session and shows a QR code. Mobile scans it to connect.
---
#### Phase 2: `awaiting-otp-input` — Enter verification code
```
Mobile shows a code User types code
│ │
▼ ▼
┌──────────────┐ submit OTP ┌──────────────┐
│ Mobile │ ◄───────────── │ Controller │
│ (shows OTP) │ │ │
└──────────────┘ └──────┬───────┘
│
▼
┌─────────────┐
│ UI │
│ (code entry)│
└─────────────┘
```
**What happens:** Mobile displays a one-time code. The user enters it in
the extension to confirm both devices are paired.
---
#### Phase 3: `awaiting-sync-offer` — Waiting for mobile
```
┌─────────────┐ ┌──────────────┐
│ UI │ ◄─────────────── │ Controller │
│ (loading) │ "validating…" │ (validates │
└─────────────┘ │ OTP) │
└──────┬───────┘
│
sync-offer │
┌──────▼───────┐
│ Mobile │
│ "ready sync" │
└──────────────┘
```
**What happens:** The extension validates the code and shows a loading
screen. Mobile confirms it is ready to receive wallets.
---
#### Phase 4: `reviewing-sync-offer` — Choose wallets & enter password
```
┌─────────────┐ pick wallets + ┌──────────────┐
│ UI │ enter password │ Controller │
│ (wallet list│ ────────────────► │ (stores │
│ + password) │ │ selection) │
└─────────────┘ └──────────────┘
```
**What happens:** The user enters their MetaMask password and selects
which wallets to sync. Only syncable wallets are shown (SRP and imported
accounts). Hardware and Snap wallets are hidden.
---
#### Phase 5: `awaiting-sync-completion` — Sending wallets to mobile
```
┌─────────────┐ ┌──────────────┐
│ UI │ ◄─────────────── │ Controller │
│ (loading) │ "syncing…" │ builds + │
└─────────────┘ │ encrypts │
│ wallet data │
└──────┬───────┘
│
sync-ready │ (encrypted wallet data)
┌──────▼───────┐
│ Mobile │
│ (imports) │
└──────────────┘
```
**What happens:** The extension packages the selected wallets
(encrypted), sends them to mobile, and shows a loading screen while
mobile imports.
---
#### Phase 6: `completed` — Done
```
┌──────────────┐
│ Controller │
│ (marks done)│
└──────┬───────┘
sync-completed│
┌──────▼───────┐
│ Mobile │
│ (finished) │
└──────────────┘
│
▼
┌─────────────┐
│ UI │
│ (success) │
└─────────────┘
```
**What happens:** Mobile confirms import is complete. The extension
shows a success screen with how many wallets and accounts were synced.
---
#### Error / cancel paths: `failed` or `cancelled`
If something goes wrong (wrong code, timeout, user cancels, mobile
disconnects), the flow stops and the user is returned to the home
screen. No wallet data is sent unless sync reaches the `sync-ready` step
successfully.
---
### Updated `sync-ready` payload schema (`QrSyncReadyData`)
When the extension is ready to sync, it sends a `sync-ready` message.
The wallet data lives in the `data` field as a list of wallet entries:
```json
{
"type": "sync-ready",
"version": "1.0.0",
"deadline": 1700000060000,
"data": [
{
"type": "Mnemonic",
"mnemonic": "<base64-encoded recovery phrase>",
"name": "Wallet 1",
"isPrimary": true,
"groups": [
{ "groupIndex": 0, "name": "Account 1", "pinned": true },
{ "groupIndex": 2, "name": "Hidden Account", "hidden": true }
]
},
{
"type": "PrivateKey",
"privateKey": "<base64-encoded private key>",
"name": "Imported Account"
}
]
}
```
**Field notes:**
| Field | Meaning |
|---|---|
| `type: "Mnemonic"` | A Secret Recovery Phrase (SRP) wallet |
| `type: "PrivateKey"` | A single imported account |
| `mnemonic` / `privateKey` | Encoded secrets (not plain text) |
| `name` | Wallet or account display name |
| `isPrimary` | Marks the main SRP wallet (only one) |
| `groups` | Which accounts from that SRP wallet to restore |
| `groupIndex` | Account position in the wallet (Account 1 = 0) |
| `hidden` / `pinned` | UI state — only included when `true` |
| `deadline` | Time limit for mobile to accept the data |
## **Changelog**
CHANGELOG entry: Added the ability to sync selected wallets and accounts
from the extension to MetaMask Mobile via QR code pairing in Settings.
## **Related issues**
Fixes:
## **Manual testing steps**
1. Set `ADD_DEVICE_SYNC_ENABLED=true` in `.metamaskrc` and rebuild the
extension.
2. Load the extension and go to **Settings → Sync with mobile**.
3. On MetaMask Mobile, start the sync flow and scan the QR code shown in
the extension.
4. Enter the verification code from mobile into the extension.
5. Wait for the wallet selection screen to appear.
6. Enter your MetaMask password and select one or more wallets (SRP
and/or imported accounts).
7. Tap **Continue** and confirm the loading screen appears, then the
success screen.
8. On mobile, verify the imported accounts match the names and count you
selected in the extension.
9. Repeat with multiple wallets and confirm only syncable wallets appear
(no Ledger/Trezor/Snap wallets in the list).
10. Test cancellation: close the flow mid-way and confirm you return to
the home screen without errors.
## **Screenshots/Recordings**
### **Before**
N/A — new feature behind `ADD_DEVICE_SYNC_ENABLED` flag.
### **After**
<!-- Add screenshots/recordings of: QR screen, OTP entry, wallet picker,
loading, and success screen -->
## **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]
> **High Risk**
> Changes how mnemonics and private keys are exported and encoded for
mobile sync, which is security-critical and contract-sensitive for the
MWP payload.
>
> **Overview**
> Completes the extension **Sync with mobile** export path by moving
secret packaging into a new **`QrSyncDataService`** and driving
selection by **account group IDs** instead of entropy IDs.
>
> **`syncAccounts`** now calls
`QrSyncDataService:buildWalletExportEntries` and sends a revised
**`sync-ready`** envelope: `deadline` at the message level and `data` as
`Mnemonic` / `PrivateKey` entries with wallet names, `isPrimary`, and
per-account `groups` metadata (names, hidden/pinned). Controller state
tracks **`qrSyncSelectedAccountGroupIds`** and drops the old
selected/imported account ID fields.
>
> The Settings **add-device** flow passes **`selectedAccountGroupIds`**
through to the background, filters the picker to syncable wallets (SRP,
HD keyring, imported private key), and uses **whole-wallet** checkboxes
only. QR sync timeouts are split into **`QR_SYNC_TIMEOUT_MS`**
(offer/completion/MWP session).
>
> Messenger init registers **`QrSyncDataService`**; the QR sync
controller messenger delegates export to the data service, which talks
to account tree and keyring actions.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
bbf9796. 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: Ganesh Suresh Patra <ganesh.patra@consensys.net>
Co-authored-by: Lionell Briones <llenoil@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
## **Description** During custom mUSD convert, pending child transactions are created alongside the parent “Converting to mUSD” row. This PR hides these internal transactions, so only the top-level convert row shows while the flow is pending. ## **Changelog** CHANGELOG entry: Fixed extra pending row during mUSD conversion flow ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/CEUX-1170 ## **Manual testing steps** 1. Open the extension Activity list (redesign). 2. Start a custom convert to mUSD flow and leave it pending/signing. 3. Confirm only one row appears: “Converting to mUSD” (no “Interaction in progress” / “With USDC” sibling). 4. Confirm the convert details Summary still shows the internal send/receive steps as before. ## **Screenshots/Recordings** ### **Before** <img width="259" height="202" alt="image" src="https://github.com/user-attachments/assets/97616dd9-0916-48fb-b8a9-f94bb8ab5999" /> ### **After** <img width="222" height="147" alt="image" src="https://github.com/user-attachments/assets/1f24906b-7d5d-4e80-8a50-19ccda333475" /> ## **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 - [ ] 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** > Activity-list filtering only; convert details still use required-transaction data elsewhere. Low risk of hiding unrelated txs unless they are linked via `requiredTransactionIds`. > > **Overview** > Fixes duplicate pending rows during **mUSD convert** by treating required child transactions as internal-only in the Activity list. > > **`selectLocalTransactions`** now drops entries whose **id** or **hash** appears in the parent’s `requiredTransactionIds` set (not just hash), so unsigned/pending relay steps no longer show as separate rows while the parent “Converting to mUSD” row is still pending. The same internal-required filter is applied to **smart transactions**, including type exclusions via `EXCLUDED_TRANSACTION_TYPES`. > > **`musdRelayDeposit`** is added to `EXCLUDED_TRANSACTION_TYPES` so relay deposit steps stay out of unified lists. Minor JSDoc was added for `smartTransactionsListSelector`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 0fd16c1. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Jira Link: https://consensyssoftware.atlassian.net/browse/TO-874 Renames the QR account-sync feature from "Add device" to "Sync accounts" and promotes it from a nested settings sub-tab to a standalone top-level `/sync-accounts` route with its own full-page layout and back button. This is a naming/relocation refactor built on top of `feat/qr-sync-controller`; no sync behavior changes. ## Changes - **Routing** - Replaced `ADD_DEVICE_ROUTE` (`/settings/add-device`) with top-level `SYNC_ACCOUNTS_ROUTE` (`/sync-accounts`). - Registered the new lazy-loaded `SyncAccounts` route in `routes.component.tsx`, still gated behind `getIsAddDeviceSyncEnabled()`. - Hid the app header on the sync-accounts page via `hideAppHeader` in `routes/utils.js`. - **Page/component rename** — moved `ui/pages/settings/add-device-tab/` → `ui/pages/settings/sync-accounts/`, renaming `AddDeviceSettings` → `SyncAccountsSettings`, `AddDeviceSettingsStep` → `SyncAccountsStep`, and related types. - **New `SyncAccountsTab`** — full-page `Page`/`Header`/`Content` wrapper with a back button that resets the controller state (`QrSyncController:resetState`) and navigates to `DEFAULT_ROUTE`. - **Settings registry & search** — updated `settings-registry.ts` and `search-config.ts` to point at the new route/labels (`addDevice` → `syncAccounts`, `ADD_DEVICE_ITEMS` → `SYNC_ACCOUNTS_ITEMS`). - **Localization** — renamed the `addDevice` message key to `syncAccounts` ("Sync with mobile") in `en` and `en_GB`. - **Tests** — added `sync-accounts-tab.test.tsx` (renders settings + back button) and renamed/updated existing settings and component tests to match new names. <!-- 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: Moved account-sync flow from settings sub-page to top level route. ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to Menu > Settings > "Sync with mobile" 2. Click on the navigation link 3. Should redirect outside settings to a `/sync-accounts` 4. Back button should redirect back to settings page ## **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/d5a39fe1-bbf3-4d93-a8b6-42af54e5aa90 <!-- [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** > Routing and naming refactor only; QR sync logic is unchanged and remains feature-flagged. > > **Overview** > Renames the QR mobile account-sync feature from **Add device** to **Sync accounts** and moves it off the nested settings path to a standalone **`/sync-accounts`** route, still behind `getIsAddDeviceSyncEnabled()`. > > The former `add-device-tab` module becomes **`sync-accounts`** (`SyncAccountsSettings`, `SyncAccountsStep`, etc.). A new **`SyncAccountsTab`** wraps the flow in a full-page layout with a back control that calls `QrSyncController:resetState` and returns to **Settings**. Settings registry gains an **`externalRoute`** flag so this tab stays in the settings menu but is mounted by the app router (not the nested `/settings/*` router), with **`hideAppHeader`** updated for the new path. > > i18n drops **`addDevice`** across locales and adds **`syncAccounts`** (“Sync with mobile”) in English locales; search/registry keys follow the rename. Tests and Jest console baselines are updated for the new paths and names—no sync controller behavior changes in this diff. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 562fd60. 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: Ganesh Suresh Patra <ganesh.patra@consensys.net> Co-authored-by: lwin <lwin.kyaw@consensys.net> Co-authored-by: Cursor <cursoragent@cursor.com> 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**
Adds structured error handling and error UI to the QR account-sync flow.
Instead of silently exiting when a sync session reaches a terminal
state, the flow now surfaces a dedicated error screen with retry/cancel,
and routes recoverable errors (expired QR, expired OTP, too many OTP
attempts) back to the relevant step so the user can recover in place.
## Changes
- **Error codes & routing** (`shared/constants/qr-sync.ts`)
- Added `QR_EXPIRED` and `OTP_ATTEMPTS_EXCEEDED` error codes and a
`QrSyncErrorCode` type.
- Added `QR_SYNC_ERROR_PHASE_OVERRIDES`, mapping certain error codes to
the step that should render: `QR_EXPIRED` -> QR scan,
`OTP_EXPIRED`/`OTP_ATTEMPTS_EXCEEDED` -> OTP input.
- **Controller error resolution** (`app/scripts/controllers/qr-sync/`)
- Refactored `#setError` to accept `{ error, code, message }` and
resolve the final code from the raw error via a new detector registry,
falling back to the provided code/message.
- Added `utils.ts` helpers: `MWP_REQUEST_EXPIRED_CODE`,
`isQrExpiredError`, `QR_SYNC_ERROR_DETECTORS`, and
`resolveQrSyncErrorCode` (maps the MWP `REQUEST_EXPIRED` error to
`QR_EXPIRED`).
- Added controller and utils unit tests for the expired-handshake paths.
- **Sync flow orchestration** (`sync-accounts-settings.tsx`)
- Replaced the auto-exit-on-terminal-phase effect with a rendered
`SyncError` screen for `CANCELLED`/`FAILED`.
- `renderStep` now derives an `effectivePhase` from the override map,
and a shared `handleRetry` resets controller state.
- **New `SyncError` component** — danger icon, title,
error-code-specific message (with a generic fallback), and Try again /
Cancel actions; exported from the components barrel.
- **`EnterVerificationCode`** — now driven by an `onRestart` prop
(parent resets the session instead of the component calling
`createSession`), reads `qrSyncError`, shows OTP-expired and
max-attempts messages, disables inputs and hides the countdown when
attempts are exhausted, and consolidates error text into a single
`errorMessage`.
- **`QrCodeScan`** — retains the last QR payload so an expired QR stays
visible instead of collapsing to a skeleton, and applies dim + blur on
expiry; removed the controller-error dimming/scan-error message path.
- **i18n** (`en`, `en_GB`) — added `add_device_error_*` strings,
`add_device_try_again`, and `enter_verification_code_max_attempts`;
removed the now-unused `qrCodeScanError`.
- **Tests** — new `sync-error.test.tsx`; updated
`enter-verification-code.test.tsx` (Redux provider + max-attempts case),
`qr-code-scan.test.tsx` (payload retention), and
`sync-accounts-settings.test.tsx` (override routing + retry/cancel).
<!--
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: QR Sync flow should now show step specific error and
global errors on a dedicated error view
## **Related issues**
Fixes:
## **Manual testing steps**
1. Go to Menu > Settings > "Sync with mobile"
2. Should redirect to QR Sync flow
3. Test QR sync expiry. Wait until QR expires
4. Restart Flow
5. Complete the QR Scan flow
6. Should show "OTP verification view"
7. Test OTP expiry. Wait until OTP expires
8. Should show OTP error.
Please refer to screenshot for the global error.
Some known incomplete flows/behavior are not implemented here, but
another PR for controllers.
- There is a controller error on reset after QR Expiration, so it does
not show yet on QR scan page.
- OT Expiry is not handled on controller side yet so, resetting the QR
Sync after this error does not work properly yet
- Only UI for max OTP attempt error is added, not controller handling
yet.
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
QR Expired
<img width="608" height="933" alt="Screenshot 2026-07-07 at 9 32 11 PM"
src="https://github.com/user-attachments/assets/38ee10e9-e030-4080-8d7d-2f6abcf6e431"
/>
OTP Expired
<img width="611" height="931" alt="Screenshot 2026-07-07 at 9 33 37 PM"
src="https://github.com/user-attachments/assets/4af56756-d5eb-4c53-8f02-a3b062c4a637"
/>
Global Account Sync Error
<img width="613" height="934" alt="Screenshot 2026-07-07 at 9 27 07 PM"
src="https://github.com/user-attachments/assets/7f7d7441-3768-435a-9713-b62a844df98c"
/>
<!-- [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**
> Touches account-sync UX and controller error classification for wallet
pairing; mistakes could mis-route users or mishandle expired sessions,
but changes are mostly UI and error mapping with tests.
>
> **Overview**
> Replaces **auto-exit on terminal QR sync phases** with in-flow error
handling: a new **`SyncError`** screen (Try again / Cancel) for
`CANCELLED`/`FAILED`, and **`QR_SYNC_ERROR_PHASE_OVERRIDES`** so
recoverable codes (`QR_EXPIRED`, `OTP_EXPIRED`, `OTP_ATTEMPTS_EXCEEDED`)
still render the QR or OTP step instead of the generic error view.
>
> **`QrSyncController`** now resolves error codes via
**`resolveQrSyncErrorCode`** / **`isQrExpiredError`**, mapping MWP
**`REQUEST_EXPIRED`** to **`QR_EXPIRED`**. **`EnterVerificationCode`**
uses parent **`onRestart`**, Redux **`qrSyncError`**, and max-attempts
messaging; **`QrCodeScan`** keeps the last QR visible on expiry
(dim/blur) and drops the old scan-error path. English i18n adds
**`add_device_error_*`** strings and removes **`qrCodeScanError`**.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
08ff1c2. 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: Ganesh Suresh Patra <ganesh.patra@consensys.net>
Co-authored-by: lwin <lwin.kyaw@consensys.net>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
Use CAIP-19 paths for fungible asset navigation and deep links, resolve wallet and metadata-backed tokens on the asset page, and harden route building against invalid ids and malformed URL params. <!-- 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: migrate asset routes to CAIP-19 identifiers ## **Related issues** Fixes: ## **Manual testing steps** Try visiting tokens that you have networks you have connected, and chains you don't have connected. This should allow users to now visit assets they do not own (but have network for). Defaults to home screen if a user does not have a valid network. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> https://github.com/user-attachments/assets/32d4caf9-61ff-4f11-96af-bfb92e2ac05b ## **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 core navigation, deep-link interstitial policy for unsigned asset URLs, and external token metadata fetching; mis-routing or bypass behavior would be user-visible across chains. > > **Overview** > Fungible asset URLs move from hex chain id + contract address to **CAIP-19** paths (`/asset/{caip-chain}/{encoded-asset-id}`), with shared helpers in `shared/lib/asset-route` for building paths, decoding route params (including Chrome vs Firefox fragment behavior), and normalizing lookups for EVM, Solana, Tron, and NFT-style routes. > > **Deep links and in-app navigation** now generate and expect those paths (`buildAssetRoutePath`), including the `/asset?assetId=…` handler. **`/asset` is added to the deep-link interstitial bypass list** so unsigned asset links open directly, aligned with mobile; deferred deep-link handling is covered by tests. > > The **asset details page** resolves holdings via `getFungibleAssetForRoute` and, when the user does not own the token, loads display metadata through `buildTokenFromCaipAssetId` / `useRouteAssetToken` (with loading and redirect-on-failure). Token list, bridge flows, and e2e bridge navigation are updated to pass and wait on CAIP-19 routes. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit cbcf34b. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
#44383) The google.svg file was removed in #44227 as part of a legacy icon cleanup. However, it is still actively referenced by the onboarding login options and reveal-SRP list flows. - Restore the original Google brand icon SVG - Move it from app/images/icons/ to app/images/ to keep it separate from the legacy icon set that is being deprecated - Update all src references in login-options.tsx and reveal-srp-list.tsx <!-- 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. --> JIRA LINK : https://consensyssoftware.atlassian.net/browse/TO-896 ## **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: restore google.svg and relocate to app/images/ ## **Related issues** Fixes: - #44334 - #44340 ## **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] --> <img width="1333" height="991" alt="Screenshot 2026-07-13 at 12 33 06 PM" src="https://github.com/user-attachments/assets/ad9b782b-fc83-4185-9045-2382ae424048" /> <img width="1287" height="990" alt="Screenshot 2026-07-13 at 12 40 53 PM" src="https://github.com/user-attachments/assets/13f821f4-93d7-40a2-8de9-5267cfc16965" /> ## **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 - [ ] 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. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Static asset and path-only UI updates with no auth, data, or business-logic changes. > > **Overview** > Restores the **Google brand icon** that was removed during legacy icon cleanup but is still required for onboarding and account flows. > > Adds `app/images/google.svg` (outside the deprecated `icons/` tree) and updates image `src` paths in **login-options** and **reveal-srp-list** from `images/icons/google.svg` to `images/google.svg` so the Google login button and SRP reveal list show the icon again. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 574bb38. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
## **Description** This PR wires the `'tron'` case into `withFixtures` and adds a smoke script so a Tron local node can be started and consumed from a test fixture. It is one reviewable step of a linear stack and replaces #44139. Together with PRs 03-05 it supersedes #43722. Based on a fresh `main` and under 1000 changed lines. ## **Changelog** CHANGELOG entry: null ## **Related issues** Part of the local-blockchain E2E initiative (WPN-536). Replaces #44139; together with the preceding Tron node PRs (config, seeder, bootstrap) supersedes #43722. ## **Manual testing steps** 1. `yarn build:test` 2. Run the Tron fixtures smoke script and confirm the `'tron'` fixture case boots a local node and tears it down cleanly. ## **Screenshots/Recordings** N/A — test infrastructure only, no user-facing UI change. ## **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** > Test-only fixture and smoke tooling; the Anvil guard is a small behavioral fix for mixed local-node fixtures. > > **Overview** > E2E fixtures can now boot a **Tron** local node via `localNodeOptions: 'tron'` (or `{ type: 'tron', options: ... }`), using the existing `TronNode` seeder alongside the Anvil path. > > **Accounts API v5** native-balance sync from `localNodes[0]` is limited to **Anvil** only, so a Tron-first fixture no longer calls `getBalance()` on a non-EVM node. > > A new **`test:e2e:smoke:local-node-ports`** script starts two java-tron networks on spaced ports, hits `getnowblock`, and tears down—sanity check for port allocation and multi-node startup. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit c91ac63. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Fixes: https://github.com/MetaMask/MetaMask-planning/issues/7467 CHANGELOG entry: null Confirmation-flow hooks and components were creating new object references and inline selector lambdas on every render, causing unnecessary downstream re-renders and Redux re-subscriptions. ## Changes ### `useGasFeeToken.ts` - Replace inline `(state) => selectTransactionAvailableBalance(state, id, chainId)` lambda with a `useMemo`-created stable selector - Wrap `useNativeGasFeeToken` and `useGasFeeToken` return objects in `useMemo`; extract `transferTransaction` into its own `useMemo` ### `smart-transactions-banner-alert.tsx` - Hoist `alertEnabled` inline typed selector lambda to a stable `selectAlertEnabled` function outside the component - Convert `getMarginStyle()` (called at render time) to a `useMemo`-computed `marginStyle` value ### `transaction-details-account-row.tsx` - Extract parameter-free selectors (`selectAccountGroupId`, `selectFirstAccountGroupName`) as stable module-level functions - Replace two parameter-dependent inline selector lambdas with `useMemo`-created selectors keyed on `from` and `selectedAccountGroupId` respectively - Wrap `displayName` derivation in `useMemo` ```ts // Before — new function reference every render const balance = useSelector((state) => selectTransactionAvailableBalance(state, transactionId, chainId), ); // After — stable reference; recreated only when deps change const selectBalance = useMemo( () => (state: unknown) => selectTransactionAvailableBalance(state, transactionId, chainId), [transactionId, chainId], ); const balance = useSelector(selectBalance); ``` <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Render/identity optimizations only; displayed account names, gas fee tokens, and banner visibility logic are unchanged. > > **Overview** > Reduces unnecessary re-renders in the confirmation flow by stabilizing Redux subscriptions and object identities. > > **`useGasFeeToken.ts`** — Parameterized `useSelector` callbacks are built with `useMemo` (e.g. balance by `transactionId`/`chainId`). `transferTransaction` and the objects returned from `useGasFeeToken` / `useNativeGasFeeToken` are wrapped in `useMemo` so consumers do not see new references every render. > > **`transaction-details-account-row.tsx`** — Stateless selectors (`selectAccountGroupId`, `selectFirstAccountGroupName`) and `getMultichainAccountsState` move to module scope. Selectors that depend on `from` or `selectedAccountGroupId` use `useMemo`; `displayName` is memoized from the resolved names. > > **`smart-transactions-banner-alert.tsx`** — The smart-transactions migration alert enabledness check is hoisted to a stable `selectAlertEnabled` used with `useSelector` instead of an inline lambda. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 3de6688. 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: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: dddddanica <zhaodanica@gmail.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 Snaps packages to enable `Blob` global in the execution environment. ## **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 support for `Blob` global in Snaps ## **Related issues** https://consensyssoftware.atlassian.net/browse/WPC-1126 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes the isolated iframe where all Snaps run and bumps core Snaps libraries, so regressions could affect every installed snap; scope is limited to a coordinated version bump with no extension app logic changes. > > **Overview** > Bumps Snaps platform dependencies so the extension loads the **11.2.0** hosted iframe execution environment instead of **11.1.1**, aligning runtime with the new package versions. > > **`package.json`** updates `@metamask/snaps-execution-environments` to `^11.2.0` and `@metamask/snaps-utils` to `^12.4.0`; **`yarn.lock`** reflects the resolved tree (including transitive bumps on snaps-sdk/superstruct inside execution-environments). **`builds.yml`** sets `IFRAME_EXECUTION_ENVIRONMENT_URL` to `https://execution.metamask.io/iframe/11.2.0/index.html` for **main**, **beta**, **experimental**, and **flask** so each build type points at the matching remote iframe. > > Per the PR description, this enables the **`Blob` global** inside the Snaps execution environment for snaps that rely on it. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit c334097. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
… comparison (#44400) ## **Description** `trackImportEvent` was not being used properly in failure scenarios and it's string comparison against strategy type was wrong. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: N/A ## **Manual testing steps** 1. Run tests 2. Confirm they pass ## **Screenshots/Recordings** N/A ## **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. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Analytics-only fix in the import account UI with no auth or import logic changes beyond event payloads. > > **Overview** > Fixes **MetaMetrics** tracking when account import fails in `import-account.js`. On catch, `trackImportEvent` now receives **`false`** instead of the error message string, so failures emit **`AccountAddFailed`** instead of being misclassified as success. > > **`trackImportEvent`** now compares `strategy` to **`'privateKey'`** (not `'Private Key'`), matching the values passed from the import flow, so **`account_import_type`** is **`PrivateKey`** vs **Json** on failures. > > Tests inject a mock **`trackEvent`** and assert failed private-key and JSON imports fire **`AccountAddFailed`** with the expected **`account_import_type`** and related properties. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit a65c69d. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…#44386) <!-- 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** Add Cursor Skill to automatically add new EVM networks to swaps <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/SWAPS-4775 ## **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** > Documentation-only; no product code, auth, or data-path changes. > > **Overview** > Adds **agent-facing documentation** for onboarding new **EVM** chains into the **unified swaps/bridge** flow, mirroring the existing non-EVM standard pattern. > > **`docs/add-evm-swaps-bridge-network.md`** is the SSOT: prerequisites (`network.ts`, `@metamask/bridge-controller`), the two-layer allowlist (hard list + `bridgeConfigV2.chainRanking`), step-by-step edits (`shared/constants/bridge.ts`, `ui/pages/bridge/utils/stablecoins.ts`, LaunchDarkly `bridgeConfigV2`), optional popular-network enablement, validation checklist, and targeted unit tests (`selectors.test.ts`, `useSmartSlippage.test.ts`). Reference PRs called out are MegaETH and Robinhood Chain. > > **`AGENTS.md`** gains an **EVM Swaps/Bridge Agent Entrypoints** section linking that doc and the Cursor skill at `.cursor/skills/mms-add-evm-swaps-bridge-network/SKILL.md`. > > No runtime bridge or swaps code changes in this diff—documentation and discoverability for agents only. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit dfb93f5. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** Removes the headless `smartTransaction:showSmartTransactionStatusPage` approval mechanism. The approval was created inside `submitSmartTransactionHook`/`submitBatchSmartTransactionHook` and immediately resolved by a UI-side shim with no more UI consuming it after removing the post STX page. Removed: - Approval request creation, update, and end-flow in `smart-transactions.ts` - `useResolveSmartTransactionApprovals` - STX filter in `selectPendingApprovalsForNavigation` - STX exclusion in `getAttentionRequiredApprovalCount` - STX rate-limit exemption in `getApprovalControllerInstanceOptions` - STX pending-approval rejection loop in `resetAccount` (there is no matching approval to reject) - Now-unused constants ## **Changelog** CHANGELOG entry: null ## **Related issues** <!-- Fixes: --> ## **Manual testing steps** 1. Submit a smart transaction 2. Verify the transaction submits, completes, and the existing toast lifecycle still fires <!-- ## **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] > **Medium Risk** > Touches smart transaction submit hooks and approval/navigation behavior; incorrect removal could affect badges or toasts, though transaction toasts remain on `useTransactionEventToasts`. > > **Overview** > Removes the headless **`smartTransaction:showSmartTransactionStatusPage`** approval path that was created during smart transaction submit and auto-resolved in the UI with no confirmation screen. > > **`SmartTransactionHook`** no longer calls `ApprovalController:addRequest` / `updateRequestState`, drops `shouldShowStatusPage` and transaction-type gating for that flow, and the hook messenger no longer depends on approval actions. Submit/batch still wait for hashes via **`SmartTransactionsController`** events. > > Related cleanup: **`SMART_TRANSACTION_CONFIRMATION_TYPES`** and UI helpers (`useResolveSmartTransactionApprovals`, `useSmartTransactionToasts`, `selectSmartTransactions`, toast type exclusions) are deleted. **`getAttentionRequiredApprovalCount`** counts all pending approvals; navigation no longer filters STX status approvals or the skip feature flag. **`resetAccount`** no longer rejects matching STX pending approvals; approval rate-limit exclusions and tests are updated accordingly. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit f6ded04. 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: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
## **Description** Migrates remaining legacy `MetaMetricsContext.trackEvent` / `trackMetaMetricsEvent` call sites in the **Web3Auth (recovery phrase, passkey, consent, password)** domain to `useAnalytics()` + `createEventBuilder` (or `trackAnalyticsEvent` for Redux thunks). Part of umbrella tracker #43885 (**15d · Web3Auth onboarding gaps**). ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** 1. Build and load the extension (`yarn start`). 2. Exercise the flows touched by this PR (see changed files). 3. With MetaMetrics debug enabled, confirm events still fire with the same names and properties. <!-- ## **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. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Analytics instrumentation refactor only; no changes to wallet, auth, or password/passkey business logic beyond how events are emitted. > > **Overview** > Replaces remaining **`MetaMetricsContext`** `trackEvent` usage in Web3Auth-related UI (basic functionality modal, change password, marketing consent, passkey troubleshoot, reveal SRP) with **`useAnalytics()`** and **`createEventBuilder().build()`**, keeping the same event names and properties. > > **Passkey troubleshoot** now pulls **page title** for support-link events from **`useSegmentContext`** instead of the legacy second-argument context merge. > > Tests for **reveal recovery phrase** (and related setup) mock **`useAnalytics`** and assert **`trackEvent`** receives the built payload shape (`name`, `properties`, `sensitiveProperties`) on SRP export success and failure paths. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 47b7b93. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until 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? --> Move status-icon so we can restore the "ui/icon" path in the list ## **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** > Import-path and lint-rule changes only; no behavior change to StatusIcon, toast, or activity UI beyond module location. > > **Overview** > **Moves `StatusIcon` out of the deprecated `ui/icon` tree** into `ui/status-icon/status-icon`, and updates imports in toast, pending activity rows, and the toast unit test mock to match. > > **Re-enables the fitness rule** that treats `ui/icon` as a blocked import path in `prevent-deprecated-imports.ts` (it had been commented out while `status-icon` still lived under `ui/icon`). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit ecb7db9. 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: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com>
…#44408) <!-- 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** Change `CODEOWNERS` to bring outstanding `ramps` code under [team money-movement](https://github.com/orgs/MetaMask/teams/money-movement) <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: [TRAM-3745](https://consensyssoftware.atlassian.net/browse/TRAM-3745) ## **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. [TRAM-3745]: https://consensyssoftware.atlassian.net/browse/TRAM-3745?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Repository governance only; no runtime or product behavior changes. > > **Overview** > Expands **Money Movement** ownership in `.github/CODEOWNERS` so more ramps-related paths require `@MetaMask/money-movement` review, alongside the existing `**/ramps/**` rule. > > Adds explicit patterns for `ui/hooks/ramps/`, `ui/selectors/rampsController/`, `ui/store/controller-actions/ramps-controller*`, `app/scripts/messenger-client-init/ramps-*` and `messengers/ramps-*`, and `test/e2e/tests/btc/mocks/ramps.ts`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit c0d234c. 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** Upgrades React and React DOM from v17 to v18 and cleans up related legacy patterns across the extension. - Bump `react` and `react-dom` from `^17.0.2` to `^18.2.0` - Remove the React 17 webpack `react/jsx-runtime` alias workaround in `development/webpack/webpack.config.ts` - Update LavaMoat policies for the dependency change - Remove `LegacyRouteMessengerProvider` and update `routes/test` helpers to use context-based providers - Replace deprecated defaultProps on function components with default parameters (UI components, `test/storybook` I18nProvider copies) - Fix async test patterns (`useCarouselManagement`, integration alerts, etc.) - Refactor `@rive-app/react-canvas` jest mock <!-- 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: MetaMask/MetaMask-planning#6925 ## **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] > **High Risk** > A core UI runtime upgrade touches the entire extension surface; regressions would affect rendering, concurrency, and user flows even though most code changes are tests and build policy. > > **Overview** > Upgrades **`react`** and **`react-dom`** from v17 to **v18.2.0**, which drives the rest of the diff: build, supply-chain policy, and test harness updates so CI and E2E stay stable under React 18’s rendering and async behavior. > > **Build & LavaMoat:** Drops the webpack **`react/jsx-runtime`** alias that only existed for React 17 ESM resolution. Regenerates LavaMoat policies so **`react`**, **`react-dom`**, and **`scheduler`** match the new package graph (e.g. **`object-assign`** paths, scheduler globals/packages). > > **Tests & tooling:** Integration setup mocks **Rive** `RuntimeLoader` so `act()` does not hang in jsdom; several notification/confirmation integration tests stop wrapping everything in **`act()`** and rely on **`waitFor`/`findBy`**. E2E helpers handle stale DOM nodes, drawer motion, send-alert modals, and notification flows. Unit/UI fixes include **`CheckBox`** **`aria-checked`**, **`useCountdownTimer`** functional updates, lighter **`useTokenSearchResults`** tests, and refreshed Jest console/snapshot baselines. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 421b31f. 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> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…44373) ## **Description** The `enableMV3TimestampSave` debug preference is obsolete now that MV3 keep-alive runs unconditionally from service worker startup (see [comment](#44348 (comment))). This PR removes the preference from controller state, UI, and persisted fixtures, and adds migration 217 to drop the field from existing profiles. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: Related: #44348 Related: #43773 ## **Manual testing steps** 1. Run `yarn start` and load the extension in Chrome. 2. Open **Settings → Advanced → Developer options** and confirm the **Service worker keep-alive** toggle is no longer shown. 3. Unlock MetaMask and confirm normal background behavior is unchanged. 4. (Optional) Upgrade from a profile that had `enableMV3TimestampSave: false` and confirm migration 217 removes the field without errors. <!-- ## **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. Made with [Cursor](https://cursor.com) --------- Co-authored-by: Cursor <cursoragent@cursor.com>
## **Description** ### Context Fixes [#44068](#44068) — an intermittent E2E failure in `reset-wallet.spec.ts` during the **second** onboarding pass after wallet reset. The failure surfaces as: ``` OnboardingFlow: failed to create new account Error: Keyring not found Error creating password Error: Keyring not found ``` `Keyring not found` is thrown from `KeyringController.exportSeedPhrase()` when the HD keyring has been cleared from memory mid-export (`keyrings[0]?.keyring` is falsy). On the create-wallet path this happens via `createNewVaultAndGetSeedPhrase` → `getSeedPhrase` → `exportSeedPhrase`. ### Root cause (confirmed) This was **reproduced locally** with the same error signature as CI. MetaMask can have **multiple UI surfaces** open at once (main window + side panel). They share one background, but each has its **own Redux store**. On second-pass onboarding password submit, the main window: 1. `createNewVault` — creates the vault and unlocks it 2. `getSeedPhrase` — exports the recovery phrase Previously these were **two separate background RPCs** with `createVaultMutex` released between them. Meanwhile, a **stale side panel** (left open after first onboarding) could react to `isUnlocked: true` while onboarding was still incomplete. Its routing reaches the onboarding **lock trap** (`OnboardingFlowSwitch` → `LOCK_ROUTE` → `setLocked`), which clears in-memory keyrings **during** step 2 → `Keyring not found`. **Why it flakes in CI / reset-wallet E2E:** The spec runs reset and second onboarding back-to-back with no human delay. The side panel can lag on `/unlock` or `/` while the main window races ahead to password submit. The dangerous window also exists in production whenever crypto work widens the gap between create and export, or when any new surface boots at `/` during export. **In short:** the main window exports the seed phrase while another surface locks the wallet. ### Fix **1. Background — atomic vault + export under one mutex** - Added `createNewVaultAndGetSeedPhrase(password)` — holds `createVaultMutex` through vault creation **and** seed export. - Added `unlockAndGetSeedPhrase(password)` — same mutex through unlock + export (import rehydration path). - Refactored vault creation into `_createNewVaultAndKeychainUnderLock(password)`; `createNewVaultAndKeychain` delegates to it (behavior unchanged). - Passed `createVaultMutex` into `LegacyBackgroundApiService` so **`setLocked` also acquires it** — lock requests wait until vault create/export completes. **2. UI — single RPC thunks** - `createNewVaultAndGetSeedPhrase` → one background call (was `createNewVault` + `getSeedPhrase`). - `unlockAndGetSeedPhrase` → one background call (was `submitPassword` + `getSeedPhrase`). - `createNewVaultAndSyncWithSocial` → uses `createNewVaultAndGetSeedPhrase`, then social backup. **3. UI — side panel mitigation** - Added `useCloseSidePanelOnWalletReset` (wired in `routes.component.tsx`). - When the side panel sees `isWalletResetInProgress` from shared background state, it calls `window.close()` so a stale panel cannot enter the onboarding lock trap during second-pass onboarding. **4. UI — duplicate submit guard** - `create-password.tsx`: `isSubmitting` state + `loading` on the form to block double password submit. **5. Tests** - `metamask-controller.actions.test.js` — `createNewVaultAndGetSeedPhrase`, `unlockAndGetSeedPhrase`. - `ui/store/actions.test.js` — single-RPC thunks, updated social-create path. - `ui/hooks/useCloseSidePanelOnWalletReset.test.ts` — side panel close behavior. - `create-password.test.tsx` — submit guard. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: #44068 ## **Manual testing steps** 1. Build a test extension: `yarn build:test` 2. Run the failing E2E spec (repeat to check for flakiness): ```bash yarn test:e2e:single test/e2e/tests/reset-wallet/reset-wallet.spec.ts --browser=chrome ``` 3. **Standard create-wallet onboarding** - Fresh profile → complete onboarding with new SRP. - Confirm password creation succeeds and SRP backup appears. 4. **Reset-wallet flow (main repro scenario)** - Complete first onboarding (side panel left open from onboarding completion). - Lock wallet → Forgot password → "I don't know my Recovery Phrase" → Reset wallet. - Complete second onboarding with a new password. - Confirm onboarding completes without `Keyring not found`. - Confirm side panel closes when reset starts (if still open). 5. **Import unlock path** - Start import onboarding, submit password on unlock step. - Confirm no `Keyring not found` during seed retrieval. 6. Confirm create-password submit is disabled while the request is in flight (double-click does not fire a second submission). <!-- ## **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] > **High Risk** > Changes vault creation, unlock, seed export, and locking serialization across background and UI—security-sensitive keyring paths where races previously caused data-loss-class failures. > > **Overview** > Fixes an intermittent **Keyring not found** failure during second-pass onboarding when vault creation and seed export were separate RPCs and another UI surface could lock the wallet in between. > > The background now exposes **`createNewVaultAndGetSeedPhrase`** and **`unlockAndGetSeedPhrase`**, each holding **`createVaultMutex`** through vault work and seed export. **`LegacyBackgroundApiService:setLocked`** also acquires that mutex so locks wait until create/export finishes. UI thunks call the single-RPC methods instead of create/unlock then **`getSeedPhrase`**, with shared **`encodeSeedPhraseForBackground`** / **`decodeSeedPhraseFromBackground`** for seed bytes over the port. > > **`useCloseSidePanelOnWalletReset`** closes the side panel when **`isWalletResetInProgress`** is set so a stale panel cannot hit the onboarding lock trap. Create-password adds **`isSubmitting`** / form **`loading`** to block double submit. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit a740b42. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…scriptions to parent (#44295) Fixes: https://github.com/MetaMask/MetaMask-planning/issues/7465 CHANGELOG entry: null Each row in the token list independently subscribed to `getMarketData`, `getCurrencyRates`, and `getNetworkConfigurationsByChainId` — triggering O(n) Redux subscriptions for data that is identical across all rows. This batch lifts those reads to the parent and memoizes derived values throughout the token list hot path. ## `token-list-item.tsx` — conditional selector lift Added optional `marketData`, `currencyRates`, `networkConfigurations` props. When the parent provides them, the component switches to a stable no-op selector so it does not subscribe to those Redux slices at all: ```ts // Module-level — typed to match the real selector so useSelector infers the // return type without unsafe `as` casts const EMPTY_MARKET_DATA: MarketDataMap = {}; const selectEmptyMarketData: typeof getMarketData = () => EMPTY_MARKET_DATA; // Inside the component — boolean flag keeps the useMemo dep array honest // without referencing the object reference (which changes every render) and // without an eslint-disable comment (which blocks React Compiler) const isMarketDataPropProvided = marketDataProp !== undefined; const marketDataSelector = useMemo( () => (isMarketDataPropProvided ? selectEmptyMarketData : getMarketData), [isMarketDataPropProvided], ); const marketDataFromStore = useSelector(marketDataSelector); const multiChainMarketData = marketDataProp ?? marketDataFromStore; ``` Fully backwards-compatible — all new props are optional; callers that don't pass them fall back to the existing direct `useSelector` path. ## `token-list.tsx` — stable callbacks Wrapped `handleTokenClick` and `renderTokenListItem` in `useCallback` with correct dependency arrays. Inlined the inner `renderTokenCell` helper to eliminate an unnecessary closure layer. ## `percentage-and-amount-change.tsx` — stale-closure fix The `useMemo` dep array was `[marketData]` while the callback also captured `balanceValue`, `conversionRate`, `currentChainId`, `fiatCurrency`, and `nativeCurrency`. The computed balance-change value would not update when those variables changed. ## `network-filter.tsx` — memoized derived values `handleFilter` wrapped in `useCallback`; `allAddedPopularNetworks` and `filter` wrapped in `useMemo` to stabilise references passed to children. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Performance and memoization-only changes with a backwards-compatible optional-prop API; the percentage change fix corrects stale UI rather than altering business rules. > > **Overview** > This PR reduces redundant work on the home **token list** and related UI by stabilizing callbacks/derived values and preparing rows to avoid **O(n) Redux subscriptions** for shared global data. > > **`TokenListItem`** gains optional `marketData`, `currencyRates`, and `networkConfigurations` props. When a parent supplies them, each row switches to stable no-op selectors so it does not subscribe to `getMarketData`, `getCurrencyRates`, or `getNetworkConfigurationsByChainId`; otherwise behavior stays the same via store fallbacks. > > **`token-list.tsx`** wraps `handleTokenClick` and `renderTokenListItem` in `useCallback` and inlines the former `renderTokenCell` helper so virtualized list render props stay stable. > > **`percentage-and-amount-change.tsx`** expands the `balanceChange` `useMemo` dependency list so fiat/balance/conversion inputs actually refresh the computed change (previously only `marketData` was listed). > > **`network-filter.tsx`** memoizes `handleFilter`, `allAddedPopularNetworks`, and the effective `filter` object passed to children. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 5486ab2. 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: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: dddddanica <zhaodanica@gmail.com>
## **Description** Migrates remaining legacy `MetaMetricsContext.trackEvent` / `trackMetaMetricsEvent` call sites in the **Platform (metametrics toggle, clear data, A/B test hook)** domain to `useAnalytics()` + `createEventBuilder` (or `trackAnalyticsEvent` for Redux thunks). Part of umbrella tracker #43885 (**15e · Platform metrics UI**). ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** 1. Build and load the extension (`yarn start`). 2. Exercise the flows touched by this PR (see changed files). 3. With MetaMetrics debug enabled, confirm events still fire with the same names and properties. <!-- ## **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. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Refactor-only analytics instrumentation with tests locking event shape; no changes to metrics opt-in, deletion tasks, or user data handling behavior. > > **Overview** > **Platform settings analytics** in the clear-metrics modal and participate-in-metrics toggle now go through `useAnalytics()` and `createEventBuilder` instead of `MetaMetricsContext.trackEvent`. Event names, categories, properties, and options such as `excludeMetaMetricsId` on deletion flows are unchanged—only the wiring API differs. > > Tests mock `useAnalytics` and assert the built event payloads for enable/disable toggles, deletion requests, and deletion failures. The shared actions mock adds a no-op `trackAnalyticsEvent` for Redux/thunk callers. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 1e1609b. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
## **Description** Migrates remaining legacy `MetaMetricsContext.trackEvent` / `trackMetaMetricsEvent` call sites in the **Settings (smart account suggestion and smart transactions opt-in thunks)** domain to `useAnalytics()` + `createEventBuilder` (or `trackAnalyticsEvent` for Redux thunks). Part of umbrella tracker #43885 (**15g · Settings Redux thunks**). ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** 1. Build and load the extension (`yarn start`). 2. Exercise the flows touched by this PR (see changed files). 3. With MetaMetrics debug enabled, confirm events still fire with the same names and properties. <!-- ## **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. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Mechanical telemetry refactor with unchanged event names and properties; preference dispatch logic is untouched. > > **Overview** > Continues the analytics migration in **Settings Redux thunks** by replacing legacy `trackMetaMetricsEvent` payloads with `trackAnalyticsEvent` + `createEventBuilder` in `ui/store/actions.ts`. > > **`setDismissSmartAccountSuggestionEnabled`** and **`setSmartTransactionsPreferenceEnabled`** still emit `SettingsUpdated` under the Settings category with the same property keys (`dismiss_smt_acc_suggestion_enabled` / `prev_*` and `stx_opt_in` / `prev_stx_opt_in`); only the construction path changes. The file now imports `createEventBuilder` (not just types) from `shared/lib/analytics/create-event-builder`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit cdabb3b. 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** MV3 keep-alive timestamp polling previously started in `background.js`, only after persisted state was loaded. That left a gap during early service worker startup, before the dynamic `background.js` import finished. This change moves the existing `saveTimestamp` + `setInterval` logic into the MV3 service worker entry points (`service-worker.ts` for webpack dev, `app-init.js` for browserify prod/E2E) so polling starts at module load. Install `event.waitUntil` for background script loading is handled separately in #44189. Removal of the obsolete `enableMV3TimestampSave` debug preference is tracked in #44373. 1. What is the reason for the change? - Keep-alive activity should begin as early as possible in the MV3 service worker lifecycle. 2. What is the improvement/solution? - Inline the existing keep-alive polling in both service worker entry points. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: #43773 ## **Manual testing steps** 1. Run `yarn start` and load the extension in Chrome. 2. Open `chrome://extensions`, click **Service worker** for MetaMask, and run: `let { timestamp } = await chrome.storage.session.get('timestamp'); console.log(timestamp)` 3. Verify a recent ISO timestamp is logged immediately after startup. 4. Reload the extension and confirm the timestamp continues updating every ~2 seconds. 5. Unlock MetaMask and perform basic actions (open popup, switch accounts) to confirm normal background behavior is unchanged. <!-- ## **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. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Behavior is unchanged aside from earlier polling start; no auth, vault, or transaction logic is touched—only duplicated keep-alive code in known MV3 entry files. > > **Overview** > **MV3 keep-alive** now starts at service worker module load instead of waiting until `background.js` finishes loading persisted state. > > The existing `saveTimestamp` + 2s `setInterval` that writes an ISO `timestamp` to `chrome.storage.session` is **inlined** in both MV3 entry points (`service-worker.ts` for webpack dev, `app-init.js` for browserify prod/E2E) and **removed** from `background.js` / `initialize()`. > > That closes the early-startup window where the worker could idle before the dynamic `background.js` import completed. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 8a73c71. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Renders the QR sync code as an `<img>` generated from a data URL instead of the table-based `QRCode` component. This ensures the QR code displays correctly on small viewports such as the side-panel view, where the previous rendering did not scale reliably. The Skeleton loader now matches the QR code's dimensions so there is no layout shift while the payload loads. ## Changes - **`qr-code-scan.tsx`** - Replaced the `QRCodeImage` component with a QR data URL generated directly via `qrcode-generator`, rendered as an `<img>` (340×340) so it displays properly on small screens like the side panel. - Memoized QR generation with `useMemo` keyed on the displayed payload to avoid regenerating on every render. - Sized the `Skeleton` loader to the same 340×340 dimensions as the QR code to prevent layout shift between the loading and loaded states. - Added a centered MetaMask fox logo overlay on a fixed white background (theme-independent) over the QR code. - **`qr-code-scan.test.tsx`** - Updated mocks to stub `qrcode-generator` (returning a mock data URL) instead of mocking the removed `QRCodeImage` component. ## Motivation The table-based `QRCode` did not render/scale reliably in the constrained side-panel viewport. Using an image sourced from a generated data URL renders consistently across screen sizes. <!-- 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: display 1:1 proportion of qr code for smaller screen ## **Related issues** Fixes: ## **Manual testing steps** 1. Open MetaMask extension on side panel mode 2. Go to Menu > Settings > Sync with mobile 3. Check QR code image ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <img width="357" height="694" alt="Screenshot 2026-07-14 at 1 01 28 PM" src="https://github.com/user-attachments/assets/0cf23a6b-551e-4d34-b494-01bd302c6b6a" /> <!-- [screenshots/recordings] --> ### **After** <img width="355" height="577" alt="Screenshot 2026-07-14 at 1 08 29 PM" src="https://github.com/user-attachments/assets/84b8a8a7-6284-49a6-919d-5474ba3549a6" /> <!-- [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** > Localized UI change on the sync-accounts QR screen with no auth or persistence impact; deeplink QR still uses the existing table-based component. > > **Overview** > **Sync-with-mobile QR** no longer uses the shared `QRCodeImage` table renderer; it builds a **data URL** with `qrcode-generator` (`createDataURL` instead of `createTableTag`) and shows a fixed **340×340** `<img>` so the code scales reliably in the side panel. > > QR generation is **memoized** on the displayed payload, the loading **skeleton** matches the same size to avoid layout shift, and a **centered MetaMask fox** sits on a theme-independent white badge over the code. Tests now mock **`qrcode-generator`** instead of `QRCodeImage`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit bdfe05e. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** After a local EVM transaction confirms, the activity list can show local state until the API query cache is refreshed after a stale time window. This PR invalidates the query cache on confirmation ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** 1. Open the extension and ensure you have at least two accounts. 2. From Account A, send a small amount of native ETH to Account B. 3. While the tx is pending, open the Activity tab — confirm the pending row appears. 4. Wait for the tx to confirm. 5. Open the confirmed tx details — verify the **Network Fee** row is present immediately after confirmation (previously it would be missing until the next stale refetch or window focus). 6. Optionally check an older confirmed tx to confirm the Network Fee row is still present there too. <!-- ## **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. 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** Tiny PR to add the filled candlestick version icon for Perps on the bottom nav when the tab is active. Behind feature flag. active <img width="443" height="72" alt="image" src="https://github.com/user-attachments/assets/3080a292-929b-463b-9c5b-af4c7f3df499" /> inactive <img width="440" height="75" alt="image" src="https://github.com/user-attachments/assets/8d42fac9-76ac-40bb-92a9-a1df2352b528" /> ## **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.
) <!-- 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? --> ```markdown ## [1.31.0] ### Changed - Use a `37 TRX` fallback fee when the network fee cannot be estimated for a transaction ([#344](MetaMask/snap-tron-wallet#344)) ## [1.30.0] ### Changed - Increase cronjob interval for account syncing from 30s to 60s ([#356](MetaMask/snap-tron-wallet#356)) ``` ## **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** Related to: https://consensyssoftware.atlassian.net/browse/WPN-1598 ## **Manual testing steps** 1. Open **offscreen.html** devtools, switch to the network tab 2. Filter by "trongrid" 3. Observe calls firing every 60 seconds ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** - [ ] 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** > No extension source changes; only a version pin update with a behavioral tweak inside the snap (less frequent sync), which is low risk for core wallet flows. > > **Overview** > Bumps the preinstalled **`@metamask/tron-wallet-snap`** dependency from **`^1.29.1`** to **`^1.31.0`** in `package.json` and refreshes **`yarn.lock`** so the extension ships the newer snap build. > > Per the linked snap release notes, this line includes slowing the **account-sync cron** from **30s to **60s**, which should cut **TronGrid** polling frequency in the offscreen snap context. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit e5bd2c1. 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** Migrates the mUSD claim toast from the custom `MerklClaimToast` component to the app-wide toast listener. This prevents overlapping toasts and keeps this mUSD toast UI consistent with other transaction toasts. ## **Changelog** CHANGELOG entry: null <!-- ## **Related issues** Fixes: --> ## **Manual testing steps** 1. From the Tokens list, claim an mUSD bonus 2. Confirm the pending toast shows "Claiming rewards..." 3. Confirm the success toast shows "Rewards claimed!" after confirmation <!-- ## **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. 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** QrSync (Settings → Sync accounts) depends on a mobile wallet scanning a QR code and exchanging messages over the Mobile Wallet Protocol (MWP) relay. That makes the happy path difficult to cover in extension E2E tests without a real mobile client or relay. This PR adds an **in-extension MWP mock stack** for test builds and wires it into the existing E2E harness: - **`mwp-dapp-client-factory`** selects the production MWP stack (`WebSocketTransport` + `SessionStore`) in normal builds, and an **`E2eMwpMockClient`** + **`MobileWalletSimulator`** when `IN_TEST` is set and Jest is not running. - **`qr-sync-e2e-bridge`** registers the simulator and handles a new background-socket command, **`qrSyncSimulate`**, so Mocha tests can drive mobile-side events (scan → OTP → sync offer → sync completed/cancel/error). - **`QrSyncController`** now initializes MWP through `getMwpDappClient` instead of wiring transport/session store inline. - **Test ergonomics:** shorter `QR_SYNC_TIMEOUT_MS` values in test builds; test builds force `ADD_DEVICE_SYNC_ENABLED` so the Sync accounts entry is available in E2E. - **E2E coverage:** page objects, `data-testid` hooks on sync-accounts UI steps, and a happy-path spec (`syncs a single HD wallet to mobile`). - **Unit tests** for `E2eMwpMockClient` and `MobileWalletSimulator`. Production behavior is unchanged outside extension test builds. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** 1. Build and load a **non-test** dev extension (`yarn start`), unlock the wallet, and confirm the extension starts without QrSync/MWP initialization errors in the background console. 2. Build and load a **test** extension (`yarn build:test`), unlock the wallet, open **Settings → Sync accounts**, and confirm the QR code screen renders and the step UI (OTP, password, wallet selection, loading, success) displays correctly. 3. With the test build loaded, walk through **Settings → Sync accounts** and confirm each step transitions as expected when mobile events are simulated (OTP entry with `123456`, password entry, wallet selection, sync confirmation). <!-- ## **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** > Refactors QrSync MWP initialization on a wallet-export path; production stack is preserved but any factory regression could break real relay pairing, while the mock stack only activates in extension test builds. > > **Overview** > Adds **extension E2E coverage** for Settings → Sync accounts by introducing a **test-build MWP mock** and wiring it through the existing background-socket harness, while **refactoring** how `QrSyncController` boots the Mobile Wallet Protocol client. > > **`mwp-dapp-client-factory`** centralizes MWP setup: normal builds still use `WebSocketTransport` + `SessionStore` + `DappClient`, but when `IN_TEST` is set **and Jest is not running**, it loads an **`E2eMwpMockClient`** and **`MobileWalletSimulator`** (via dynamic `require` so test helpers stay out of production bundles). `QrSyncController` now calls **`getMwpDappClient`** instead of owning transport/session fields inline. > > E2E tests drive the mobile side with a new **`qrSyncSimulate`** background-socket command handled by **`qr-sync-e2e-bridge`** (scan → OTP → sync offer → completed/cancel/error). **`QR_SYNC_TIMEOUT_MS`** uses shorter values under `IN_TEST` so flows finish quickly. > > The compile-time flag is renamed **`ADD_DEVICE_SYNC_ENABLED` → `QR_SYNC_ENABLED`** (`.metamaskrc`, `builds.yml`, `environment.ts`, docs). **Test builds force `QR_SYNC_ENABLED=true`** so the Sync accounts tab is available in E2E. > > Supporting changes: **`data-testid`** hooks across sync-accounts UI steps, settings/sync page objects, a happy-path **`qr-sync.spec.ts`**, and unit tests for the factory (Jest still uses the production stack mocks). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 0a84dab. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Signed-off-by: lwin <lwin.kyaw@consensys.net> Co-authored-by: Ganesh Suresh Patra <ganesh.patra@consensys.net> Co-authored-by: Lionell Briones <llenoil@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
…o metamask-ci (#44387) ## **Description** The GitHub App `mm-token-exchange-service` (App ID `3202397`) is being renamed to `metamask-ci` in the MetaMask org. On rename, its bot login changes from `mm-token-exchange-service[bot]` to `metamask-ci[bot]`. This PR updates the one place in this repo that hardcodes the old bot slug: - `.github/workflows/cla.yml`: CLA `allowlist:` entry `mm-token-exchange-service[bot]` → `metamask-ci[bot]` (no other entries changed). **⚠️ Merge in lockstep with the app rename — merge this immediately *after* TechOps renames the app, not before.** Tracked in INFRA-3680 / INFRA-3764. This ordering is deliberate and security-relevant: merging at/after the rename means `metamask-ci[bot]` is trusted only once we actually own that name, and the old `mm-token-exchange-service[bot]` is dropped the instant its name is freed — so there is no window where an unowned/freed GitHub App name is trusted by the CLA allowlist. This PR is kept review-ready so the merge is a single click during the coordinated cutover window. ## **Changelog** CHANGELOG entry: null ## **Related issues** Refs: https://consensyssoftware.atlassian.net/browse/INFRA-3680 Refs: https://consensyssoftware.atlassian.net/browse/INFRA-3763 ## **Manual testing steps** 1. After TechOps renames the app to `metamask-ci` and this merges, have `metamask-ci[bot]` open a PR / post an automated comment. 2. Confirm the CLA check auto-approves it via the updated allowlist (no CLA failure on the bot's contribution). Note: CI/config-only change; rename behavior validated in a `Consensys-test` dry-run (bot login updates in place, App ID unchanged) — see INFRA-3762. ## **Screenshots/Recordings** N/A — CI workflow configuration change; no extension UI or runtime behavior is affected. ### **Before** N/A ### **After** N/A ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask 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.
Builds ready [8423f22]
⚡ Performance Benchmarks (Total: 🟢 12 pass · 🟡 8 warn · 🔴 4 fail)
Bundle size diffs
🍒 What's in this RCCherry-picks (2 commits)
Changelog (223 commits from main at RC cut)
AI Test Plan
Release Scenarios (14)High Risk Scenarios (7)1. State Migrations – Core data integrity (accounts, networks, tokens/NFTs)Risk Level: HIGH Why This Matters: Migrations 217–219 were added; any schema or state transformation can cause data loss or corrupted lists affecting core wallet functionality. Test Steps:
2. State Migrations – Connected sites and permissionsRisk Level: HIGH Why This Matters: Permissions/connection mappings may be reshaped by migrations and are critical for dapp connectivity and the unconnected-account alert logic. Test Steps:
3. State Migrations – Settings and feature flagsRisk Level: HIGH Why This Matters: Settings schema changes can silently reset critical privacy/security preferences or analytics consent. Test Steps:
4. Token Management – Assets Controller v11: token discovery and watchAssetRisk Level: HIGH Why This Matters: A major Assets Controller bump commonly affects token metadata, decimals, and persistence; regressions break balances and swaps. Test Steps:
5. NFT Management – Assets Controller v11: detection, metadata, and transfersRisk Level: HIGH Why This Matters: NFT indexing/metadata often changes across assets controller updates; broken metadata or transfer handling impacts key user flows. Test Steps:
6. Bridge – Quote, approvals, switching, and status trackingRisk Level: HIGH Why This Matters: Bridge controller changes can disrupt quoting, approvals, network switching, and status polling, leading to failed or stuck transfers. Test Steps:
7. Network Management – Dapp-driven add/switch chainRisk Level: HIGH Why This Matters: Network enablement controller changes risk breaking dapp workflows that add/switch chains, impacting many ecosystem integrations. Test Steps:
Medium Risk Scenarios (7)1. Message Encryption – eth_getEncryptionPublicKey and eth_decryptRisk Level: MEDIUM Why This Matters: Small controller changes here can silently break EIP‑1024 flows used by secure messaging features. Test Steps:
2. Alert System – Unconnected account alertRisk Level: MEDIUM Why This Matters: Alert-system code changed; incorrect alerts can block signing or confuse users about which account is connected. Test Steps:
3. Alert System – Multiple alerts and confirmation modalsRisk Level: MEDIUM Why This Matters: Refactors to alert components can cause modal stacking and lifecycle issues that hide critical prompts. Test Steps:
4. API Error Handling – RPC/network failuresRisk Level: MEDIUM Why This Matters: api-error-handler changes must surface actionable errors; failures here strand users with spinners and no recovery path. Test Steps:
5. Swaps – Quote, allowance, slippage, and executionRisk Level: MEDIUM Why This Matters: Assets controller changes affect token metadata and allowances used in swaps; regressions can misprice or fail swaps. Test Steps:
6. Permissions Management – Connected sites UIRisk Level: MEDIUM Why This Matters: Migrations and alert changes rely on accurate permissions state; UI regressions can misrepresent connections. Test Steps:
7. Performance/UX – Popup and assets rendering at scaleRisk Level: MEDIUM Why This Matters: Large-scale UI refactors can degrade performance and responsiveness, impacting everyday use. Test Steps:
Teams Sign-off StatusSigned off: None yet Awaiting sign-off (9): Generated by AI Test Plan Analyzer (gpt-5) at 2026-07-23T22:39:17.116Z AI generated test plan (JSON): test-plan-13.42.0.json |
|
@SocketSecurity ignore npm/@metamask/gator-permissions-snap@2.4.0 |
Builds ready [189763c]
⚡ Performance Benchmarks (Total: 🟢 12 pass · 🟡 8 warn · 🔴 4 fail)
Bundle size diffs
🍒 What's in this RCCherry-picks (3 commits)
Changelog (223 commits from main at RC cut)
AI Test Plan
Release Scenarios (13)High Risk Scenarios (8)1. State Migrations (217–219): Core wallet state on upgradeRisk Level: HIGH Why This Matters: Multiple new migrations can corrupt or reset critical user state (accounts, networks, assets, permissions) if misapplied. Test Steps:
2. Permissions migration: Connected Sites per-account integrityRisk Level: HIGH Why This Matters: Migrations that touch permissions risk cross-account leakage or broken connections, directly impacting security and dapp usability. Test Steps:
3. Token Management: Assets Controller v11 – auto-detect and manual addRisk Level: HIGH Why This Matters: A major Assets Controller bump can change detection, metadata, and fiat price handling—errors here misrepresent balances and can trigger user loss. Test Steps:
4. NFTs: Detection, metadata, and visibilityRisk Level: HIGH Why This Matters: Changes in asset controllers can break NFT indexing or metadata resolution, leading to missing or incorrect collectibles. Test Steps:
5. Security: Unconnected account alert during approvals/signaturesRisk Level: HIGH Why This Matters: Updated alert components and tests target this flow; regressions here can cause accidental approvals from unintended accounts. Test Steps:
6. Message encryption flows: eth_getEncryptionPublicKey and eth_decryptRisk Level: HIGH Why This Matters: Controller changes in decrypt/encryption flows directly affect sensitive cryptographic operations and data privacy. Test Steps:
7. Network Management: dapp-triggered add/switch network (addEthereumChain/switch)Risk Level: HIGH Why This Matters: Controller patches around network enablement can break or weaken validation, causing failed switches or unsafe network additions. Test Steps:
8. Transaction submission: RPC/gas errors surfaced via API Error HandlerRisk Level: HIGH Why This Matters: Changes to API error handling can leave users stuck during critical send flows or mask important failure details. Test Steps:
Medium Risk Scenarios (5)1. Signature requests: personal_sign and typed data (EIP-712)Risk Level: MEDIUM Why This Matters: Large UI and controller diffs risk regressing signature rendering or account-context handling. Test Steps:
2. Alerts system: stacking, dismissal, and confirm flowsRisk Level: MEDIUM Why This Matters: Broad changes to alert components and utilities can cause missing alerts, incorrect stacking, or action misfires. Test Steps:
3. Bridge: quote retrieval and handoffRisk Level: MEDIUM Why This Matters: Bridge controller patching can break quote fetching or routing, stranding users mid-flow. Test Steps:
4. Portfolio/Fiat display: token price and totalsRisk Level: MEDIUM Why This Matters: Asset controller changes can affect pricing sources and conversion logic, risking misleading balances. Test Steps:
5. Network switching within the extension (picker and per-account)Risk Level: MEDIUM Why This Matters: Controller and UI refactors can subtly break network-context state, confusing users and dapps. Test Steps:
Teams Sign-off StatusSigned off: None yet Awaiting sign-off (9): Generated by AI Test Plan Analyzer (gpt-5) at 2026-07-23T23:55:51.210Z AI generated test plan (JSON): test-plan-13.42.0.json |
…lower viewport cp-13.42.0 (#44854) - feat: keep the balance left aligned for lower viewport cp-13.42.0 (#44791) This PR is to make sure that the balance is left aligned for smaller viewports ## **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** 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** https://github.com/user-attachments/assets/91524f4d-55e2-44ca-8f00-71a89b3c2f98 ## **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** > Presentation-only layout changes in wallet overview with no auth, data, or business-logic impact. > > **Overview** > **Wallet overview balance alignment** is updated so the sidepanel keeps the balance **left-aligned** when the viewport is at or below **490px**, while fullscreen/sidepanel layouts still **center** the balance on wider widths. > > Adds a **`wallet-overview-sidepanel`** class on the sidepanel environment and a shared SCSS mixin that applies `start` alignment under that breakpoint for the balance block, coin overview balance, and loading skeleton. Inline Tailwind alignment on the balance wrapper and skeleton is removed in favor of these styles, and the sidepanel max-width is centralized as a SCSS variable. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit e2e6500. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> [5d2cff8](5d2cff8) Co-authored-by: Nidhi Kumari <nidhi.kumari@consensys.net>
… cp-13.42.0 (#44856) - fix(activity): transaction details width (#44853) <!-- 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** Align the activity transaction details max-width with the recently updated app max width ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: #44840 ## **Manual testing steps** 1. Open Activity and click a transaction. 2. Resize the window through narrow, mid (~600–900px), and wide widths. 3. Confirm details always match the app content width with no Activity showing around the edges. 4. Repeat in sidepanel while resizing the panel. <!-- ## **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 - [ ] 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. Made with [Cursor](https://cursor.com) Co-authored-by: Cursor <cursoragent@cursor.com> [b6619a9](b6619a9) Co-authored-by: Francis Nepomuceno <n3ps@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Builds ready [5738947]
⚡ Performance Benchmarks (Total: 🟢 16 pass · 🟡 4 warn · 🔴 4 fail)
Bundle size diffs
🍒 What's in this RCCherry-picks (5 commits)
Changelog (223 commits from main at RC cut)
AI Test Plan
Cherry-Pick Scenarios (1)Medium Risk Scenarios (1)1. Activity Transaction Details Width (responsive fix)Risk Level: MEDIUM Why This Matters: Cherry-pick 44856 fixes a layout issue in transaction details; regressions here can make critical information (amounts, addresses, CTAs) inaccessible on small viewports. Test Steps:
Release Scenarios (11)High Risk Scenarios (7)1. State Migrations (217–219)Risk Level: HIGH Why This Matters: Migrations can corrupt or drop user data (accounts, networks, assets, preferences). Early detection prevents data loss and broken UX post-upgrade. Test Steps:
2. Token Management (Assets Controller v11 upgrade)Risk Level: HIGH Why This Matters: A major Assets Controller bump can affect detection, balances, metadata, and chain scoping—core wallet functionality users rely on daily. Test Steps:
3. NFTs (Collectibles) Detection and TransfersRisk Level: HIGH Why This Matters: NFT logic depends on asset metadata and balances; controller or UI changes can break detection, display, and transfer accuracy. Test Steps:
4. Network Enablement and Chain SwitchingRisk Level: HIGH Why This Matters: Network enablement gating and switching are core to cross-chain usage; regressions can strand users or cause incorrect chain interactions. Test Steps:
5. Send Flow and EIP-1559 (Speed Up/Cancel)Risk Level: HIGH Why This Matters: Any regression in EIP-1559 or replacement flows can cause failed or stuck transactions and user fund risk. Test Steps:
6. Dapp Transaction Confirmation and Typed Data SigningRisk Level: HIGH Why This Matters: Confirmation surfaces and typed data rendering must be accurate to prevent phishing or signing the wrong data. Test Steps:
7. Bridge Flow (Bridge Controller update)Risk Level: HIGH Why This Matters: Bridge logic is multi-step and cross-chain; controller or UI regressions can create failed moves of funds or confusing states. Test Steps:
Medium Risk Scenarios (4)1. Activity Feed and Transaction Details (general)Risk Level: MEDIUM Why This Matters: Large UI updates can break detail rendering and discoverability, making it hard for users to audit transactions. Test Steps:
2. Alerts System (Unconnected Account, Multiple Alerts)Risk Level: MEDIUM Why This Matters: Alert presentation and CTA wiring guide users to safe states; regressions can lead to mistaken actions on the wrong account/network. Test Steps:
3. API Error Handling (User-Facing Errors)Risk Level: MEDIUM Why This Matters: Error copy and handling prevent user confusion and repeated failed attempts, especially after controller/UI refactors. Test Steps:
4. Encryption Public Key and Decrypt (eth_getEncryptionPublicKey / eth_decrypt)Risk Level: MEDIUM Why This Matters: Even small changes here can break privacy-focused dapp features or expose confusing prompts that impact security-sensitive flows. Test Steps:
Teams Sign-off StatusSigned off: None yet Awaiting sign-off (7): Generated by AI Test Plan Analyzer (gpt-5) at 2026-07-24T17:29:39.713Z AI generated test plan (JSON): test-plan-13.42.0.json |
Builds ready [d5f6239]
⚡ Performance Benchmarks (Total: 🟢 10 pass · 🟡 8 warn · 🔴 4 fail)
Bundle size diffs [🚀 Bundle size reduced!]
🍒 What's in this RCCherry-picks (7 commits)
Changelog (223 commits from main at RC cut)
AI Test Plan
Cherry-Pick Scenarios (2)High Risk Scenarios (1)1. Security – Deep-link interstitial protectionRisk Level: HIGH Why This Matters: Cherry-pick 44830 fixes a regression that removed interstitial protection for deep links; without it, malicious links could trigger wallet prompts without user awareness. Test Steps:
Medium Risk Scenarios (1)1. Activity – transaction details width/overflowRisk Level: MEDIUM Why This Matters: Cherry-pick 44856 fixes transaction details width issues; without it, users may miss critical info or misclick actions in the Activity panel. Test Steps:
Release Scenarios (11)High Risk Scenarios (9)1. State Migration (217–219) – vault, accounts, permissionsRisk Level: HIGH Why This Matters: Multiple new migrations (217–219) can corrupt or drop critical state (accounts, permissions, networks) if ordering or shape assumptions changed. Test Steps:
2. State Migration (217–219) – tokens, NFTs, activity historyRisk Level: HIGH Why This Matters: Migrations touching asset state can orphan tokens/NFTs or break activity history, directly impacting user trust and balances visibility. Test Steps:
3. Token Management – Assets Controller v11 upgrade (watchAsset, detection, fiat pricing)Risk Level: HIGH Why This Matters: A major Assets Controller change can break watchAsset flows, auto-detection, and pricing—core to portfolio accuracy. Test Steps:
4. Transaction Confirmation – EIP-1559 gas editing and submissionRisk Level: HIGH Why This Matters: Widespread UI updates can regress confirmation flows and gas editing, risking failed or overpaid transactions. Test Steps:
5. Swaps – quotes, approval, executionRisk Level: HIGH Why This Matters: Token metadata and UI refactors can disrupt the Swaps funnel (approvals/quotes), risking failed trades or wrong balance updates. Test Steps:
6. Message Signing – personal_sign and eth_signTypedData_v4Risk Level: HIGH Why This Matters: UI changes can break or misrepresent signing prompts, exposing users to phishing or incorrect consent. Test Steps:
7. Encryption APIs – getEncryptionPublicKey and eth_decryptRisk Level: HIGH Why This Matters: Small controller changes to decrypt-message/encryption key paths can silently break privacy-preserving flows dapps rely on. Test Steps:
8. Network Management – add/switch chain via dappRisk Level: HIGH Why This Matters: Network controller and UI changes risk incorrect chain setup/switching, leading to failed dapp interactions. Test Steps:
9. Alert System – unconnected account banner and multi-alert handlingRisk Level: HIGH Why This Matters: Alert system refactors can hide or misprioritize critical warnings, leading to accidental actions with the wrong account. Test Steps:
Medium Risk Scenarios (2)1. Activity View – details readability and copy controlsRisk Level: MEDIUM Why This Matters: Numerous UI updates can degrade transaction detail readability, hurting user ability to audit past actions. Test Steps:
2. API Error Handling – Send and Swap failuresRisk Level: MEDIUM Why This Matters: The API error handler changed; poor surfacing of RPC/validation errors can lead to user confusion and repeated failures. Test Steps:
Teams Sign-off StatusSigned off: None yet Awaiting sign-off (9): Generated by AI Test Plan Analyzer (gpt-5) at 2026-07-24T20:34:46.264Z AI generated test plan (JSON): test-plan-13.42.0.json |
Builds ready [fbd3a5e]
⚡ Performance Benchmarks (Total: 🟢 15 pass · 🟡 5 warn · 🔴 4 fail)
Bundle size diffs [🚀 Bundle size reduced!]
🍒 What's in this RCCherry-picks (8 commits)
Changelog (223 commits from main at RC cut)
AI Test Plan
Cherry-Pick Scenarios (2)High Risk Scenarios (2)1. Deep Links Interstitial ProtectionRisk Level: HIGH Why This Matters: Cherry-pick 44830 fixes restoration of deep link interstitial protections; without it, external links could bypass expected user warnings and increase phishing risk. Test Steps:
2. App Link (https) Deep Links InterstitialRisk Level: HIGH Why This Matters: Cherry-pick 44830 fixes interstitial gating for web-based deep links; it ensures users cannot be silently funneled into privileged flows without an explicit checkpoint. Test Steps:
Release Scenarios (11)High Risk Scenarios (6)1. State Migrations (versions 217–219)Risk Level: HIGH Why This Matters: State migrations can corrupt or drop user data (accounts, connections, custom networks, token/NFT lists). Verifying upgrade integrity prevents data loss and post-upgrade breakages. Test Steps:
2. Token Management and Balances (Assets Controller v11)Risk Level: HIGH Why This Matters: A major Assets Controller update can alter token discovery, metadata, and balance calculations. Errors here directly impact asset visibility and user trust in balances. Test Steps:
3. NFTs (Detection, Metadata, Transfer)Risk Level: HIGH Why This Matters: NFT handling relies on the same asset plumbing; regressions can break detection, metadata display, or transfers, degrading core wallet functionality for NFT users. Test Steps:
4. Network Management (Add/Switch via dapp and UI)Risk Level: HIGH Why This Matters: Changes in network enablement can break EIP-3085/EIP-3326 flows, preventing users from onboarding to new chains or causing permission inconsistencies. Test Steps:
5. Message Encryption/Decryption (eth_getEncryptionPublicKey, eth_decrypt)Risk Level: HIGH Why This Matters: Changes in decrypt/encryption key controllers can break dapp workflows or introduce cross-account data exposure, a significant security risk. Test Steps:
6. Transaction Signing and Activity DetailsRisk Level: HIGH Why This Matters: Core transaction flows are sensitive to UI and controller refactors; regressions can lead to incorrect confirmations or broken activity history. Test Steps:
Medium Risk Scenarios (5)1. Fiat Conversion and Display ConsistencyRisk Level: MEDIUM Why This Matters: Incorrect fiat conversion or inconsistent rendering undermines decision-making and trust in displayed portfolio values. Test Steps:
2. Bridge Flow (Quotes, Approvals, Cancellations)Risk Level: MEDIUM Why This Matters: Bridge controller updates can affect quoting, approvals, and cleanup; issues here can strand approvals or mislead users about transfer status. Test Steps:
3. Connected Sites and Unconnected Account AlertRisk Level: MEDIUM Why This Matters: Recent alert and related UI changes can affect safety prompts; missing or incorrect alerts may cause users to transact with unintended accounts. Test Steps:
4. Alert Modals and Stacking BehaviorRisk Level: MEDIUM Why This Matters: Changes in the alert system utilities can break modality and focus management, causing users to get stuck or miss important warnings. Test Steps:
5. API Error Handling and Recovery (RPC failures)Risk Level: MEDIUM Why This Matters: Resilience to RPC failures ensures the wallet remains usable and clearly communicates connectivity issues without compromising functionality. Test Steps:
Teams Sign-off StatusSigned off: None yet Awaiting sign-off (7): Generated by AI Test Plan Analyzer (gpt-5) at 2026-07-25T01:38:05.291Z AI generated test plan (JSON): test-plan-13.42.0.json |
🚀 v13.42.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