Skip to content

release: 13.40.0 - #44326

Merged
HowardBraham merged 175 commits into
stablefrom
release/13.40.0
Jul 20, 2026
Merged

HowardBraham merged 175 commits into
stablefrom
release/13.40.0

Conversation

@metamaskbot

@metamaskbot metamaskbot commented Jul 9, 2026 •

Copy link
Copy Markdown
Collaborator

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

  • Developer Teams:
    Conduct regression and exploratory testing for your functional areas, including automated and manual tests for critical workflows.
  • QA Team:
    Focus on exploratory testing across the wallet, prioritize high-impact areas, and triage any Sentry errors found during testing.
  • Customer Success Team:
    Validate new functionalities and provide feedback to support release monitoring.

GitHub Signoff

  • Each team must sign off on the Release Candidate (RC) via GitHub by the end of the validation timeline (Tuesday EOD PT).
  • Ensure all tests outlined in the Testing Plan are executed, and any identified issues are addressed.

Issue Resolution

  • Resolve all Release Blockers (Sev0 and Sev1) by Tuesday EOD PT.
  • For unresolved blockers, PRs may be reverted, or feature flags disabled to maintain release quality and timelines.

Cherry-Picking Criteria

  • Only critical fixes meeting outlined criteria will be cherry-picked.
  • Developers must ensure these fixes are thoroughly reviewed, tested, and merged by Tuesday EOD PT.

🗓️ Timeline and Milestones

  1. Today (Friday): Begin Release Candidate validation.
  2. Tuesday EOD PT: Finalize RC with all fixes and cherry-picks.
  3. Wednesday: Buffer day for final checks.
  4. Thursday: Submit release to app stores and begin rollout to 1% of users.
  5. Monday: Scale deployment to 10%.
  6. Tuesday: Full rollout to 100%.

✅ Signoff Checklist

Each team is responsible for signing off via GitHub. Use the checkbox below to track signoff completion:

Team sign-off checklist

  • Accounts
  • Assets
  • Bots Team
  • Confirmations
  • Core Extension UX
  • Core Platform
  • Design System
  • Engagement
  • Extension Platform
  • Money Movement
  • Networks
  • Ocap Kernel
  • Onboarding
  • Perps
  • Product Safety
  • Rewards
  • Swaps and Bridge
  • Transactions

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

seaona and others added 30 commits July 2, 2026 19:02
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**
The update-fixture script was broken due to the new cache build logic.
This issue was fixed here:

#43194 

However, this has unmasked an issue with permissions in the repo (cannot
fully test in the fork, that's why it was not catched there):


1. In prepare, the Cache dist artifact step failed because of this error
`##[warning]Failed to save: Unable to reserve cache with key
dist-f2a11c162c. cache write denied: token has no writable scopes`


https://github.com/MetaMask/metamask-extension/actions/runs/28595056443/job/84790275152

<img width="1074" height="138" alt="image"
src="https://github.com/user-attachments/assets/fc4a041d-ad76-4f58-9c3c-9f617be5d719"
/>

2. In update-fixtures, Restore dist artifact has fail-on-cache-miss:
true, so it hard-failed, the cache was never written.

<img width="875" height="244" alt="image"
src="https://github.com/user-attachments/assets/930526d4-788f-4cd1-80af-6728cb65bee6"
/>


## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

1. Not easy manual steps. Best effort: look into the failure and see fix

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [ ] 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**
> CI-only workflow permission tweak with no application or runtime
behavior changes.
> 
> **Overview**
> Fixes the **Update E2E fixtures** workflow by giving the `prepare` and
`update-fixtures` jobs explicit token scopes.
> 
> Each job now declares `permissions: contents: read` and `actions:
write` so steps that **download** build artifacts from another run (`gh
run download`), **save/restore** cache entries, and **upload** test
artifacts can run under the default `GITHUB_TOKEN` instead of failing on
missing `actions` access. Commit/push behavior is unchanged and still
relies on `FIXTURE_UPDATE_TOKEN` in later jobs.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
654d27a. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Sub-PR of umbrella tracker
[#43885](#43885).

Migrates MetaMetrics `trackEvent` call sites in this CODEOWNERS domain
to `createEventBuilder` + `trackEvent` via `useAnalytics()` (UI) or
`app/scripts/controllers/analytics` (background).

**Dependency note:** Can merge in parallel with other domain PRs.

**Files in this PR:** 26

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Part of analytics migration umbrella: #43885

## **Manual testing steps**

1. Check out this branch and run `yarn start`.
2. Exercise flows in the touched domain (see diff file list).
3. Confirm no console errors and representative events still fire.

<!--
## **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-only refactor with no change to conversion, claim, or DeFi
product logic; risk is mainly telemetry shape/pipeline regressions,
covered by updated unit and integration tests.
> 
> **Overview**
> This PR moves **earn / mUSD** and related **DeFi** analytics off
legacy `MetaMetricsContext` / `MetaMetricsController:trackEvent` onto
the shared **`createEventBuilder` + `trackEvent`** path (`useAnalytics`
in UI, `app/scripts/controllers/analytics` in background).
> 
> **UI:** mUSD CTAs, claim badge, convert links, education screen, and
transaction-status hooks now build events with the builder (`name`,
category in `properties`, optional `sensitiveProperties`) instead of
flat `{ event, category, properties }` payloads.
> 
> **Background:** `DeFiPositionsController` gets a local `trackEvent`
adapter that maps legacy controller payloads into built analytics
events; the init messenger no longer delegates
**`MetaMetricsController:trackEvent`**.
> 
> **Tests:** mocks switch from `metametrics` context to `useAnalytics`;
integration DeFi tests assert **`trackAnalyticsEvent`** and the new
event/options shape.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
d716d33. 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**

Sub-PR of umbrella tracker
[#43885](#43885).

Migrates MetaMetrics `trackEvent` call sites in this CODEOWNERS domain
to `createEventBuilder` + `trackEvent` via `useAnalytics()` (UI) or
`app/scripts/controllers/analytics` (background).

**Dependency note:** Can merge in parallel with other domain PRs after
PR1.

**Files in this PR:** 29

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Part of analytics migration umbrella: #43885

## **Manual testing steps**

1. Check out this branch and run `yarn start`.
2. Exercise flows in the touched domain (see diff file list).
3. Confirm no console errors and representative events still fire.

<!--
## **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]
> **Medium Risk**
> Wide refactor across privacy, security, and passkey flows could subtly
change analytics payloads or context (e.g. page title,
excludeMetaMetricsId), though product behavior is unchanged.
> 
> **Overview**
> This PR continues the umbrella analytics migration by replacing
**`MetaMetricsContext`** `trackEvent` usage across **settings** (about,
assets, preferences, privacy, security, developer tools, shared toggles)
with **`useAnalytics()`** and the **`createEventBuilder` → `build()`**
event shape.
> 
> Call sites now build events with **`addCategory` / `addProperties`**
instead of legacy `{ category, event, properties }` objects. Notable
behavioral tweaks: **About** contact-us tracking pulls **page title**
from **`useSegmentContext`** instead of
`contextPropsIntoEventProperties`; **delete MetaMetrics data**
success/error events pass **`excludeMetaMetricsId`** via **`build({
excludeMetaMetricsId: true })`** instead of a second `trackEvent`
options argument.
> 
> Tests drop **`MetaMetricsContext.Provider`** wrappers and **mock
`useAnalytics`** (often with the real **`createEventBuilder`**),
asserting the new payload shape (`name`, `properties.category`,
`sensitiveProperties`).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f70ace8. 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**

Sub-PR of umbrella tracker
[#43885](#43885).

Migrates MetaMetrics `trackEvent` call sites in this CODEOWNERS domain
to `createEventBuilder` + `trackEvent` via `useAnalytics()` (UI) or
`app/scripts/controllers/analytics` (background).

**Dependency note:** Can merge in parallel with other domain PRs after
PR1.

**Files in this PR:** 19

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Part of analytics migration umbrella: #43885

## **Manual testing steps**

1. Check out this branch and run `yarn start`.
2. Exercise flows in the touched domain (see diff file list).
3. Confirm no console errors and representative events still fire.

<!--
## **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 plumbing and test updates only; event names and properties
are intended to stay equivalent aside from the builder payload shape.
> 
> **Overview**
> Confirmation and send flows stop using **`MetaMetricsContext`** for
**`trackEvent`** and instead build events with **`createEventBuilder`**
from **`useAnalytics()`**, matching the umbrella analytics migration.
> 
> Send metrics hooks (**amount**, **asset**, **recipient** selection)
and related confirmation hooks
(**`useTrackERC20WithoutDecimalInformation`**, snap transaction loading
screen, permit value display tests) follow the same pattern;
**`excludeMetaMetricsId: false`** is preserved where it was passed
before via **`.build({ excludeMetaMetricsId: false })`**.
> 
> **`useSimulationMetrics`** also refactors incomplete-asset tracking:
**`SimulationIncompleteAssetDisplayed`** fires inside a **`useEffect`**
(with **`useMemo`** for display-name lookup) instead of during render,
while still deduplicating with **`processedAssets`**. Tests mock
**`useAnalytics`** instead of wrapping components in
**`MetaMetricsContext.Provider`**.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
305e278. 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**

Fixes a crash in the transaction confirmation footer: `BigNumber Error:
times() number type has more than 15 significant digits`.

**Cause:** BigNumber rejects raw JS numbers with more than 15
significant digits, since floats lose precision past that point. It only
trusts strings for values that precise. The price API can return prices
like `0.07086574003221964`, and a couple of hooks were passing that
value into `.times()` as a number instead of a string.

**Fix:** convert the value to a string before it hits BigNumber, in:
- `useEthFiatAmount.js`
- `useGasFeeToken.ts`
- `Numeric.ts` (`numberToBigNumber`) — the shared helper other number
conversions rely on, so this doesn't keep resurfacing elsewhere.

<!--
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: bignumber incident 1752

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-3528

## **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/ff2711fe-b071-48e0-a65d-bbda4d5ecae4


<!-- [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**
> Narrow string-coercion change at BigNumber boundaries for fiat
display; no auth, signing, or transaction submission logic is modified.
> 
> **Overview**
> Fixes a **transaction confirmation crash** (`BigNumber Error: times()
number type has more than 15 significant digits`) when fiat conversion
rates from the price API exceed JavaScript’s safe float precision (e.g.
`0.07086574003221964`).
> 
> **`numberToBigNumber`** in `Numeric.ts` now builds decimal
`BigNumber`s from `String(value)` instead of the raw number, so shared
`Numeric` construction and **`applyConversionRate`** no longer throw on
long rates. **`useEthFiatAmount`** and **`useGasFeeToken`** likewise
pass **`String(conversionRate)`** into `.times()` so hook-level fiat
math matches that behavior.
> 
> Tests cover high-precision construction, conversion rates, and
gas-fee-token fiat display.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
22a656b. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Version Bump After Release

This PR bumps the main branch version from 13.39.0 to 13.40.0 after
cutting the release branch.

### Why this is needed:
- **Nightly builds**: Each nightly build needs to be one minor version
ahead of the current release candidate
- **Version conflicts**: Prevents conflicts between nightlies and
release candidates
- **Platform alignment**: Maintains version alignment between MetaMask
mobile and extension
- **Update systems**: Ensures nightlies are accepted by app stores and
browser update systems

### What changed:
- Version bumped from `13.39.0` to `13.40.0`
- Platform: `extension`
- Files updated by `set-semvar-version.sh` script

### Next steps:
This PR should be **manually reviewed and merged by the release
manager** to maintain proper version flow.

### Related:
- Release version: 13.39.0
- Release branch: release/13.39.0
- Platform: extension
- Test mode: false

---
*This PR was automatically created by the
`create-platform-release-pr.sh` script.*

Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
## **Description**

Upgrades design system packages to align with the [v50.0.0
release](https://github.com/MetaMask/metamask-design-system/releases/tag/v50.0.0)
([release
PR](MetaMask/metamask-design-system#1303)).

**Packages upgraded:**
- `@metamask/design-system-react`: `^0.29.0` → `^0.30.0`
- `@metamask/design-system-shared`: `^0.25.0` → `^0.26.0`

**Unchanged (already at latest for this release line):**
- `@metamask/design-system-tailwind-preset`: `^0.10.0`
- `@metamask/design-tokens`: `^8.6.0`

**Breaking changes addressed:**

None. Release 50.0.0 is additive only.

**New additions available for future use:**
- `IconName.HardDrive` — hard-drive icon across shared, React web, and
React Native packages
([#1302](MetaMask/metamask-design-system#1302))

**Legacy component deprecations:**
- No new `@deprecated` JSDoc notices were added in this release.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

Feature: Design system upgrade to v50.0.0

  Scenario: Core app functionality is unaffected
    Given I am on the main app screen
When I navigate through the primary user flows (home, send, settings)
    Then the UI renders correctly with no visual regressions

  Scenario: Banner and tag surfaces render correctly
Given I view screens that use design-system banners or tags (e.g.
alerts, network notices)
    When the page loads
    Then banners and tags display with expected spacing and colors

## **Screenshots/Recordings**

### **Before**

N/A – dependency-only update

### **After**

N/A – dependency-only update

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


Made with [Cursor](https://cursor.com)

Co-authored-by: Cursor <cursoragent@cursor.com>
…ile's workflow, aligns Extension RC notifications with Mobile (#42960)

## **Description**

Adds Extension RC release notification improvements, aligned with the
Mobile RC notification experience:

- Adds an `RC Slack notify` workflow that runs after successful `Main`
workflow runs on semver `release/**` branches.
- Gates automated Slack posting on an open release PR targeting `stable`
with the `auto-rc-builds` label.
- Adds a manual `workflow_dispatch` path for testing Slack notifications
with explicit `head_sha`, `semver`, `github_run_id`, and `test_channel`
inputs.
- Posts RC Slack messages with Extension build artifact links, changelog
entries, a build pipeline link, and a “What’s in this RC” details link.
- Adds a “What’s in this RC” section to prerelease PR comments,
including cherry-picks since `origin/main` and changelog commits since
the previous release tag.

Aligns Extension RC notifications with Mobile by adding:
- Cherry-picks and changelog sections to RC PR comments (collapsible
tables with anchors)
- "What's in this RC" link in Slack notifications pointing to PR
#whats-in-this-rc anchor
- "View Build Pipeline" link in Slack footer

## **Testing performed**

- Verified the Slack notification workflow in
`consensys-test/metamask-extension-howard`.
- End-to-end run from this release branch
consensys-test#72
  - Slack message was posted, and the links worked

## **Changelog** 

CHANGELOG entry: null

## **Related issues**

Fixes:


https://consensyssoftware.atlassian.net/browse/MCRM-76?actionerId=62972968b407cc0069ffc438&sourceType=assign&atlOrigin=eyJpIjoiNGI2NmFjNGFiNjUzNGIyMmEyMDBlNjZmMGE3Mzk5M2QiLCJwIjoiaiJ9

Fixes: MetaMask/MetaMask-planning#7458

<!--## **Manual testing steps**-->
## **Screenshots/Recordings**

### **Before**
<img width="543" height="392" alt="Screenshot 2026-05-27 at 1 54 28 AM"
src="https://github.com/user-attachments/assets/2c3a0c82-3f60-477b-9542-fb5c26d0577b"
/>

### **After**
After - What's in this RC section added (this is Mobile RC PR
screenshot, section should look the same for the Extension RC PR
comment):
<img width="546" height="809" alt="Screenshot 2026-05-27 at 1 53 50 AM"
src="https://github.com/user-attachments/assets/6a0002e0-1d84-4b99-95c4-914b08bf1afa"
/>

<!--## **Pre-merge author checklist**
## **Pre-merge reviewer checklist**-->


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches release CI (Slack, PR comments, git history) where mistakes
could mis-link builds or omit RC details, but failures are treated as
non-critical and secrets stay scoped to existing announce flows.
> 
> **Overview**
> **RC Slack notifications** now gate on an open `release/*` → `stable`
PR with `auto-rc-builds`, pass **`BUILD_RUN_ID`** and **`PR_NUMBER`**,
and post Block Kit messages with Webpack/Browserify zips, changelog
snippets, **View Build Pipeline** / **View full release notes** footers,
and a **What’s in this RC** link to a run-scoped PR anchor
(`#user-content-whats-in-this-rc-{runId}`). The notify job checks out
**default-branch** notification scripts while loading **`package.json` /
`CHANGELOG.md` from the release commit**.
> 
> **Prerelease PR comments** on `release/*` gain a **What’s in this RC**
block: cherry-picks since `merge-base` with `origin/main` and changelog
commits since the prior semver tag, rendered as collapsible tables (or a
failure message). **`publish-prerelease`** fetches fuller git history
for that section, finds the release PR via paginated open PRs matched by
branch/repo, and uses **`BUILD_ANNOUNCE_TOKEN`** instead of
`PR_COMMENT_TOKEN`.
> 
> **`getBuildLinks`** moves to **`build-links.ts`** (re-exported from
`artifacts.ts`) for Slack, nightly posts, and announce tooling;
**`slack-rc-notification.mts`** runs via **`node`** with typed imports.
Unit tests cover build links and cherry-pick extraction/markdown.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
75330e7. 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: Howard Braham <howrad@gmail.com>
## **Description**

Adds React Refresh support to development webpack watch builds while
keeping webpack-dev-server's built-in HMR client out of non-UI extension
runtimes.

The current implementation:

- Disables webpack-dev-server's automatic `hot`, `liveReload`, and
client injection, then registers MetaMask-specific dev-server clients
from `setupMiddlewares` once the resolved WebSocket port is known.
- Prepends the React Refresh runtime and `ui-client` only to the UI
runtime, so React UI pages can receive Webpack HMR updates without
injecting HMR code into service workers, content scripts, or other
privileged entries.
- Uses a dev-server protocol with two update messages:
- `mm:background-update-fingerprint` for background/privileged-code
changes that require `browser.runtime.reload()`.
- `mm:ui-update-hash` for UI-only rebuilds that should trigger a React
Refresh/Webpack hot update in open UI pages.
- Fingerprints manifest scripts, background/service-worker code, and
privileged HTML page entries after successful builds. If that
fingerprint changes, the background client reloads the extension; if it
does not, UI clients receive the UI build hash and ask their own Webpack
runtime to check for hot updates.
- Handles MV3 by bundling the background client into the service worker
entry, and MV2 by injecting a standalone `background-client` entry into
the background page.
- Patches `@pmmmwh/react-refresh-webpack-plugin` with a `runtimeEntry`
option so its automatic runtime injection can be disabled; MetaMask
injects the runtime explicitly through `reactRefreshLoader` instead.
- Adds the `webpack/hot/emitter` project type declaration and extends
webpack unit coverage for the dev-server client wiring, update
announcements, WebSocket message validation/reconnect behavior, React
Refresh loader wiring, and SWC React refresh options.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: MetaMask/MetaMask-planning#7277

## **Manual testing steps**

1. Run `yarn start`.
2. Reload the unpacked extension in Chrome.
3. Open a React UI page, for example the onboarding welcome page.
4. Edit a visible React component, for example remove a button in
`ui/pages/onboarding-flow/welcome/welcome-login.tsx`.
5. Save the file.
6. Verify the visible UI updates without manually reloading the
extension page or reloading the whole extension.
7. Verify the service worker console does not receive webpack-dev-server
HMR update handling for that UI-only change.
8. Edit a background or privileged-code file.
9. Save the file and verify the extension reloads instead of attempting
a UI hot update.


## **Screenshots/Recordings**

Not applicable: this is build tooling/dev-server behavior with no
persistent 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]
> **Medium Risk**
> Changes are confined to development watch tooling but touch extension
reload/HMR wiring, privileged entry injection, and a patched third-party
webpack plugin—incorrect behavior could cause missed updates or unwanted
reloads in local dev only.
> 
> **Overview**
> **Development watch builds** now enable **React Refresh** and
**Webpack HMR** for UI code only, without injecting webpack-dev-server’s
default HMR client into service workers, content scripts, or other
privileged entries.
> 
> For **dev development + `--watch`**, the config adds
`HotModuleReplacementPlugin`, `@pmmmwh/react-refresh-webpack-plugin`
(with `runtimeEntry: false`), and SWC rules scoped to `UI_DIR_RE` with
`refresh: true`. A patched plugin adds **`runtimeEntry`** so automatic
React Refresh entry injection is off; **`reactRefreshLoader`** prepends
the React Refresh runtime and **`ui-client`** to the UI load entry via a
`pre` rule from **`setupUiClient`**.
> 
> **Dev-server wiring** moves from a static `DEV_SERVER_OPTIONS` to
**`getDevServerOptions({ uiClientRule })`** on the webpack config;
**`build.ts`** starts WDS with `options.devServer`. Custom clients
replace full-page UI reload: **`ui-client`** listens for
**`mm:ui-update-hash`** and emits `webpackHotUpdate`;
**`background-client`** handles **`mm:background-update-fingerprint`**
and triggers `browser.runtime.reload()` when privileged code changes.
**`setupBackgroundClient`** still chooses extension reload vs UI update
from build fingerprints. MV2 HTML injection drops the old UI reload
entry; **`injectEntryScripts`** skips `.hot-update.` chunks.
> 
> Also adds **`react-refresh`** dependency, LavaMoat policy entries for
the plugin, **`webpack/hot/emitter`** types, and expanded unit tests
(dev-server, loader, webpack config, WebSocket reconnect/`isDone`
behavior).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f089dc1. 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: Howard Braham <howrad@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**

<!--
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?
-->

Replacement for
#42914 as CI made it
impossible to merge that PR.

## **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: change the native asset icon (RBTC) for Rootstock

## **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**
> Static image swap only; no logic, auth, or network behavior changes.
> 
> **Overview**
> Replaces **`app/images/rootstock-native.svg`** with a new artwork used
wherever **`ROOTSTOCK_NATIVE_TOKEN_IMAGE_URL`** points (Rootstock
mainnet and testnet native RBTC in the wallet UI).
> 
> The old asset was a large, multi-path illustration (green/orange
palette, oversized viewBox). The new one is a **560×560** hex badge with
orange **`#ff9100`** fill and a white Bitcoin mark, with simplified CSS
classes. No TypeScript or wiring changes—only the SVG file.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
24b7caa. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…cp-13.39.0 (#44006)

<!--
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 integrates the `QuoteStatusManager` from
`@metamask/bridge-status-controller` v74 into MetaMask Mobile, aligning
mobile with the extension's bridge quote status tracking.

**Reason for change:** Bridge swaps need server-side quote status
tracking (submit/update/poll) so the backend can correlate user
transactions with bridge quotes. `@metamask/bridge-status-controller`
v74 exposes this via `QuoteStatusManager`, gated behind a remote feature
flag.

**Solution:**
- Bumps `@metamask/bridge-status-controller` to `^74.0.0` and
`@metamask/transaction-pay-controller` to `^23.17.2`
- Wires `BridgeStatusController` init with:
  - `clientProduct: 'metamask-mobile'`
- `isQuoteStatusManagerEnabled` — reads the `bridgeQuoteStatusManager`
remote feature flag (respects local overrides)
- `onQuoteStatusManagerError` — reports `QuoteStatusUpdateError` to
Sentry; `QuoteStatusGetError` is not reported (expected polling
failures)
- Registers `bridgeQuoteStatusManager` in the E2E feature flag registry
(enabled by default for version `8.2.0`)
- Adds `quoteUpdateStatusStore` to test fixtures and bridge API mocks
for `GET /getQuoteStatus` and `POST /quote/updateStatus`


<!--
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-4452

## **Manual testing steps**

```gherkin
Feature: Bridge Quote Status Manager

  Scenario: Quote status manager is disabled by default
    Given the app is installed with default remote feature flags
    When a bridge/swap transaction is initiated
    Then no requests are made to /getQuoteStatus or /quote/updateStatus

  Scenario: Quote status manager tracks swap quote lifecycle when enabled
    Given the bridgeQuoteStatusManager remote feature flag is enabled (via local override or LaunchDarkly)
      And the user has a funded wallet on a supported source chain
    When the user completes a bridge or swap transaction
    Then the app sends a POST to /quote/updateStatus with SUBMITTED status after tx submission
      And the app polls GET /getQuoteStatus for quote status updates
      And bridge transaction history continues to display correctly in Activity

  Scenario: Quote status update errors are reported to Sentry
    Given bridgeQuoteStatusManager is enabled
      And the /quote/updateStatus endpoint returns an error
    When a swap transaction is submitted
    Then a QuoteStatusUpdateError is captured in Sentry
      And QuoteStatusGetError polling failures are NOT captured in Sentry
```
## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches bridge swap submission/polling and transaction-batch wiring
behind a feature flag; mis-flag or error-handling behavior could affect
bridge activity without blocking swaps when disabled.
> 
> **Overview**
> Integrates **bridge quote status tracking** from
`@metamask/bridge-status-controller` **v74** by bumping that package
(and `@metamask/transaction-pay-controller`) and extending
`BridgeStatusController` initialization with **`clientProduct` /
`clientVersion`**, a remote-flag gate **`isQuoteStatusManagerEnabled`**
(`bridgeQuoteStatusManager`), and **`onQuoteStatusManagerError`** that
sends **`QuoteStatusUpdateError`** to Sentry while ignoring
**`QuoteStatusGetError`**.
> 
> Exposes new persisted/UI state **`quoteUpdateStatusStore`** (fixtures,
background types, metrics snapshots) and excludes it from Sentry state
reporting. **LavaMoat** policies grant `fetch` / interval timers to the
updated controller package.
> 
> Also adds **Stellar pubnet** (`XlmScope.Pubnet`) to featured
multichain network chain IDs and refreshes lockfile transitive MetaMask
deps.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
27b7626. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
…nAccountService:createNextMultichainAccountGroup` (#44103)

## **Description**

This binds the `createNextMultichainAccountGroup` `getApi()` method
directly to the
`MultichainAccountService:createNextMultichainAccountGroup` messenger
action, removing the redundant `MetamaskController` wrapper. The UI
thunk is updated to pass `{ entropySource }` so the argument shape
matches the action's signature.

## **Changelog**

CHANGELOG entry:null

## **Related issues**

Progresses: https://consensyssoftware.atlassian.net/browse/WPC-1090

## **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**
> Small wiring refactor with an explicit argument-shape fix; behavior
should be unchanged if the service already expected `{ entropySource }`.
> 
> **Overview**
> Removes the **`MetamaskController`** wrapper for
**`createNextMultichainAccountGroup`** and exposes **`getApi()`** as a
direct **`controllerMessenger.call`** to
**`MultichainAccountService:createNextMultichainAccountGroup`**.
> 
> The UI thunk and its test now pass **`{ entropySource }`** (stripped
wallet id) instead of a bare string, so the background RPC matches the
messenger action’s expected argument shape.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
99e2b31. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
Remove left-over code following up
#43461
The "Turn on notifications" modal usage has been removed. This PR
removes remaining files and translations

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

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**
> Dead-code and i18n cleanup only; no remaining references to the
removed modal or strings in the repo.
> 
> **Overview**
> Removes leftover **Turn on MetaMask notifications** UI after the modal
was already disconnected from product flows in a prior change.
> 
> The `TurnOnMetamaskNotifications` component, its test, barrel export,
and `TURN_ON_METAMASK_NOTIFICATIONS` entry in the central modal registry
are deleted. Locale strings used only by that modal
(`turnOnMetamaskNotifications*`, except
`turnOnMetamaskNotificationsError`) are dropped across all
`app/_locales` files. Jest console baseline no longer tracks the removed
test file.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
21f4da2. 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**

Move `AddressBookController` initialization to `@metamask/wallet@6.0.0`.
The controller is now wired inside the wallet library with no
extension-specific instance options required.

Deletes the local init file, messenger file, and their tests. Resolves
the instance via `this.wallet.getInstance('AddressBookController')` in
`MetaMaskController`. No functional changes.

## **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. Build the extension and open it.
2. Add, edit, and delete a contact in the address book.
3. Confirm contacts persist across page reloads.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches persisted contact data and controller startup order via a
major @metamask/wallet bump; behavior should match if wallet init is
equivalent, but regressions in add/edit/persist need manual
verification.
> 
> **Overview**
> **Address book** is no longer bootstrapped in the extension; it comes
from **`@metamask/wallet@6.0.0`**, which now owns
**`AddressBookController`** initialization (including
**`@metamask/address-book-controller`**).
> 
> The extension drops the local **`AddressBookControllerInit`**,
restricted messenger factory, and their tests, and removes
**`AddressBookController`** from **`messengerClientInitFunctions`** and
**`MESSENGER_FACTORIES`**. **`MetaMaskController`** resolves the
controller with **`this.wallet.getInstance('AddressBookController')`**,
same as **`AccountsController`** and **`KeyringController`**.
> 
> **LavaMoat** policies are updated so **`@metamask/wallet`** may use
**`@metamask/address-book-controller`**. **`package.json`** /
**`yarn.lock`** bump **`@metamask/wallet`** from **5.0.0** to **6.0.0**.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
22148c9. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
## **Description**

Sub-PR of umbrella tracker
[#43885](#43885).

Migrates MetaMetrics `trackEvent` call sites in this CODEOWNERS domain
to `createEventBuilder` + `trackEvent` via `useAnalytics()` (UI) or
`app/scripts/controllers/analytics` (background).

**Dependency note:** Can merge in parallel with other domain PRs after
PR1.

**Files in this PR:** 28

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Part of analytics migration umbrella: #43885

## **Manual testing steps**

1. Check out this branch and run `yarn start`.
2. Exercise flows in the touched domain (see diff file list).
3. Confirm no console errors and representative events still fire.

<!--
## **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]
> **Medium Risk**
> Touches many onboarding funnel telemetry paths; wrong event shape
could skew metrics, but behavior is largely a refactor with updated test
coverage.
> 
> **Overview**
> Onboarding UI analytics moves off **`MetaMetricsContext.trackEvent`**
onto **`useAnalytics()`** with
**`createEventBuilder(...).addCategory(...).addProperties(...).build()`**
across password creation, SRP import/review/confirm, MetaMetrics opt-in,
privacy settings, wallet-ready completion, and related screens.
**`MetaMetricsContext`** is still used where needed for tracing (e.g.
buffered traces on create-password and recovery flows).
> 
> **`onboarding-flow`** wires social-import unlock through a
**`trackLegacyEventForAction`** adapter so
**`restoreSocialBackupAndGetSeedPhrase`** keeps receiving the old
payload shape while events are built with the new API.
> 
> **Tests and tooling:** unit tests mock **`useAnalytics`**
(create-password asserts on **`name`** instead of **`event`**);
integration onboarding tests expect background **`trackAnalyticsEvent`**
with **`name`** / **`properties`** (category nested in properties).
Storybook aliases **`useAnalytics`** to a no-op mock; Import SRP stories
drop the MetaMetrics provider wrapper.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
942625f. 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**

Sub-PR of umbrella tracker
[#43885](#43885).

Migrates MetaMetrics `trackEvent` call sites in this CODEOWNERS domain
to `createEventBuilder` + `trackEvent` via `useAnalytics()` (UI) or
`app/scripts/controllers/analytics` (background).

**Dependency note:** Can merge in parallel with other domain PRs after
PR1.

**Files in this PR:** 15

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Part of analytics migration umbrella: #43885

## **Manual testing steps**

1. Check out this branch and run `yarn start`.
2. Exercise flows in the touched domain (see diff file list).
3. Confirm no console errors and representative events still fire.

<!--
## **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]
> **Medium Risk**
> Analytics event shape and property placement change across onboarding
and OAuth callbacks, which could alter Segment payloads if builders
differ from legacy context merging; user-facing onboarding behavior is
unchanged.
> 
> **Overview**
> Onboarding **welcome and account-status flows** now emit MetaMetrics
through **`useAnalytics()`** and
**`createEventBuilder().addCategory().addProperties().build()`** instead
of legacy `MetaMetricsContext.trackEvent({ category, event, properties
})`.
> 
> **`useAccountStatusContext`** sources `trackEvent` /
`createEventBuilder` from analytics while keeping buffered traces on
`MetaMetricsContext`. **Welcome** adds **`trackLegacyEventForAction`**
so **`startOAuthLogin`** still receives a legacy-shaped callback that is
converted to builder events. **Login error modal** drops context-based
tracking; support-link events use **`useSegmentContext`** for `location`
(e.g. page title **Welcome**) instead of
`MetaMetricsContextProp.PageTitle`.
> 
> Tests mock **`useAnalytics`** (and segment context where needed) and
assert the new payload shape (`name` + `properties` including
`category`). **`txDataSelector`** uses optional chaining on
`confirmTransaction` as a small unrelated hardening.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
c671f60. 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**

Sub-PR of umbrella tracker
[#43885](#43885).

Migrates MetaMetrics `trackEvent` call sites in this CODEOWNERS domain
to `createEventBuilder` + `trackEvent` via `useAnalytics()` (UI) or
`app/scripts/controllers/analytics` (background).

**Dependency note:** Can merge in parallel with other domain PRs after
PR1.

**Files in this PR:** 21

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Part of analytics migration umbrella: #43885

## **Manual testing steps**

1. Check out this branch and run `yarn start`.
2. Exercise flows in the touched domain (see diff file list).
3. Confirm no console errors and representative events still fire.

<!--
## **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]
> **Medium Risk**
> Touches analytics emission across OAuth onboarding failures and Shield
subscription flows; behavior should be equivalent but any regression
could skew product metrics or drop pre-consent buffered events.
> 
> **Overview**
> Migrates **Shield, subscription, OAuth, and related UI** from legacy
`MetaMetricsController:trackEvent` / `MetaMetricsContext` to
**`createEventBuilder` + `trackEvent`**
(`app/scripts/controllers/analytics` in background, `useAnalytics()` in
UI).
> 
> **Background:** `SubscriptionService` drops the
`MetaMetricsController:trackEvent` messenger delegate and emits Shield
metrics (cohort assignment, subscription requests, payment method
changes, rewards opt-in) via the analytics module. `OAuthService` no
longer accepts an injected `trackEvent`; social login failure events use
the builder API while **pre–opt-in buffering** still maps built events
back to `addEventBeforeMetricsOptIn` when onboarding/opt-in are
incomplete.
> 
> **UI:** Modals (`AddFundsModal`, support data consent) and
`useSubscriptionMetrics` switch to `useAnalytics`, with a shared
`trackShieldEvent` helper to reduce duplication. Support link clicks now
put **page title** on the event properties (via `useSegmentContext`)
instead of the old `contextPropsIntoEventProperties` option.
> 
> Tests are updated to mock `useAnalytics` / `controllers/analytics` and
to split OAuth init mocks between `MetaMetricsController` and
`AnalyticsController` for opt-in state.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
e77a542. 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**

Extracted mockAuthenticatedUserStorageNotificationPreferences into
test/e2e/helpers/authenticated-user-storage/mocks.ts and removed it from
identity mocks. Global E2E setup now imports it directly from the
dedicated file.
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

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**

- [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 refactor of mock registration and URL matching; no
production code paths.
> 
> **Overview**
> **Authenticated User Storage** notification-preferences E2E mocking is
moved out of `test/e2e/tests/identity/mocks.ts` into
`test/e2e/helpers/authenticated-user-storage/mocks.ts`, so it is no
longer bundled with identity/auth `mockIdentityServices`.
> 
> Global setup in `mock-e2e.js` now registers that mock directly next to
identity APIs. Behavior is unchanged (in-memory GET 404 until PUT, then
GET returns prefs), but the mock URL matcher now covers **dev-api**,
**uat-api**, and **api** user-storage hosts via regex instead of a
single production URL.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
bb0ab5e. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Sub-PR of umbrella tracker
[#43885](#43885).

Migrates MetaMetrics `trackEvent` call sites in this CODEOWNERS domain
to `createEventBuilder` + `trackEvent` via `useAnalytics()` (UI) or
`app/scripts/controllers/analytics` (background).

**Dependency note:** Can merge in parallel with other domain PRs after
PR1.

**Files in this PR:** 9

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Part of analytics migration umbrella: #43885

## **Manual testing steps**

1. Check out this branch and run `yarn start`.
2. Exercise flows in the touched domain (see diff file list).
3. Confirm no console errors and representative events still fire.

<!--
## **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; event names and property
semantics are preserved with updated payload structure. Low risk to
backup/sync behavior aside from verifying metrics still fire in manual
testing.
> 
> **Overview**
> This PR moves **Backup and Sync** MetaMetrics tracking onto the shared
**`createEventBuilder` + `trackEvent`** pattern used elsewhere in the
analytics migration.
> 
> **UI** components (`BackupAndSyncToggle`, feature toggles, turn-on
modal) drop **`MetaMetricsContext`** in favor of **`useAnalytics()`**,
building events with **`name`** / **`properties.category`** (plus
**`sensitiveProperties`**) instead of top-level **`event`** /
**`category`**. **Tests** mock **`useAnalytics`** and assert the new
payload shape.
> 
> **Background** contact-sync callbacks in
**`UserStorageControllerInit`** call
**`trackEvent(createEventBuilder(...).build())`** from
**`app/scripts/controllers/analytics`** instead of
**`initMessenger.call('MetaMetricsController:trackEvent', ...)`**. The
user-storage **init messenger** no longer delegates
**`MetaMetricsController:trackEvent`** (
**`AllowedInitializationActions`** is **`never`** ).
> 
> **`privacy-settings.test.tsx`** adds a **`useAnalytics`** mock so
onboarding privacy tests still run with child components that use the
new hook.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
e20763d. 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>
#44128)

<!--
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**
We still have permissions issues with the update-fixture script, after
adding read/write permissions:
<img width="2148" height="276" alt="image"
src="https://github.com/user-attachments/assets/32ef0098-a51f-4599-b7cd-87f58f05aae5"
/>

The reason is because of a github policy change in 26-06-2026,
[Read-only Actions cache for untrusted
triggers](https://github.blog/changelog/2026-06-26-read-only-actions-cache-for-untrusted-triggers/)
So we can no longer save caches.

This PR replaces the cache-based job-to-job handoffs in
update-e2e-fixtures.yml with artifacts, and revert the permissions
change (no effect)

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

1. It's utterly complex to test the same conditions on a fork. After PR
is merged we can create a test PR.
There's very low risk, as if broken, the only thing that won't work is
the update-fixtures job (which is currently already broken) and only
triggered by the bot comment (we have the manual alternative as
workaround)

## **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**
> CI-only change to a bot-triggered fixture update workflow; no
application or runtime behavior changes.
> 
> **Overview**
> Restores the **@metamaskbot update-e2e-fixture** flow after GitHub’s
read-only Actions cache policy for untrusted triggers (e.g.
`issue_comment` on PRs), which blocked `cache/save` between jobs.
> 
> **prepare** now uploads the downloaded `build-dist-webpack` bundle as
`dist-<commit-sha>`; **update-fixtures** downloads that artifact instead
of restoring a cache, then uploads regenerated `onboarding-fixture.json`
and `default-fixture.json` as `fixtures-<commit-sha>`.
**commit-updated-fixtures** downloads those fixtures into
`test/e2e/fixtures` before diffing and committing.
> 
> Job-level `contents: read` / `actions: write` permissions added for
cache writes are removed. Upload steps use `if-no-files-found: error`
and `overwrite: true` so re-runs can replace prior artifacts.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
61a4abe. 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**

Switching accounts (and many other quick operations) **always** briefly
flashed the full-screen loading overlay. For operations that resolve in
a few milliseconds, the spinner makes the app feel slower

This PR adds a `useSpinDelay` hook that withholds the spinner until
loading has run for at least a certain duration, and once shown pins it
for a minimum duration to prevent flicker on the way out.

Summary:
- fast operations no longer flash a spinner
- genuinely slow operations still show one


## **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: chore: defer global spinners

## **Related issues**

Fixes:

## **Manual testing steps**

1.Unlock the wallet and open the account list
2. Switch between accounts several times
3. Verify no loading spinner flashes during the switch
4. Open Settings and toggle a few preferences


## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**



https://github.com/user-attachments/assets/35785229-a9c5-4e82-978a-ad2fac88bd8d


https://github.com/user-attachments/assets/aac6568c-51f4-44df-854c-bc1fdcd51a87





<!-- [screenshots/recordings] -->

### **After**


https://github.com/user-attachments/assets/ce2a590d-2d56-4a53-a4f6-a8ecacf94c16



https://github.com/user-attachments/assets/ce3025aa-cdac-4098-adc6-389a679b56ac




<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> UI-only timing change on the global loading overlay with no auth,
data, or API impact; behavior is covered by unit tests.
> 
> **Overview**
> Adds **`useSpinDelay`** so the full-screen loading overlay no longer
appears on very short `appState.isLoading` bursts (e.g. account
switching).
> 
> The hook waits **300ms** before showing a spinner and, once visible,
keeps it up for at least **400ms** to avoid flicker. **`Routes`** now
gates the overlay with `showLoadingOverlay = useSpinDelay(isLoading)`
instead of tying visibility directly to `isLoading`; existing guards
(onboarding, confirmations, redesigned flows, deep link) are unchanged.
> 
> Unit tests cover delay, min duration, early resolution, defaults, and
unmount cleanup.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
b2a8591. 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 sets the codeowners of `app/scripts/metamask-controller.js` to
`core-platform` and `extension-platform`

## **Changelog**

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**
> Process-only change to review requirements; no runtime or build
behavior is modified.
> 
> **Overview**
> Updates **`.github/CODEOWNERS`** so changes to
**`app/scripts/metamask-controller.js`** require review from
**@MetaMask/extension-platform** and **@MetaMask/core-platform**, with a
new co-ownership comment for that path.
> 
> The **metamask-template-renderer** entry comment is updated from Snaps
to **Core Platform** (owners unchanged). A prior **Confirmations and
Snaps** comment block is removed in favor of these sections.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
9219389. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…e and removes one (#44094)

<!--
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**

Test is failing in CI: Ledger Account 2 was partially scrolled out of
view, so clicking its options button didn't open the dropdown menu.

Added `scrollToElement()` before clicking the options button in
`openMultichainAccountMenu`, ensuring the account is fully visible
before the click.

CI
[logs](https://github.com/MetaMask/metamask-extension/actions/runs/28572596324/job/84715535505)

## **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**

<img width="780" height="493" alt="test-failure-screenshot-1"
src="https://github.com/user-attachments/assets/2dcba58a-c1ad-4bb8-8ba0-ee0db027cc2d"
/>


### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> E2E page-object locator change only; no production wallet or extension
runtime behavior is affected.
> 
> **Overview**
> **`openMultichainAccountMenu`** no longer uses a CSS `aria-label`
selector plus `findElements` and an array index. It now clicks through a
new **indexed XPath** helper that matches
`multichain-account-cell-end-accessory` by quoted `"{accountLabel}
options"` and picks the **(srpIndex + 1)** match when duplicate labels
exist across SRPs.
> 
> `srpIndex` defaults to **0** via destructuring, and the click goes
through **`driver.clickElement({ xpath })`** instead of manually
indexing WebElements.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
7004750. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
`getUnconnectedAccounts` was an unmemoized function that called
`.filter()` on every invocation, returning a new array reference even
when the underlying accounts and permissions hadn't changed — triggering
unnecessary re-renders in the connections UI.

CHANGELOG entry: null
Fixes: https://github.com/MetaMask/MetaMask-planning/issues/6411

## Changes

- **`ui/selectors/selectors.js`** — Converts `getUnconnectedAccounts`
from a plain function to a `createSelector`-memoized selector using
`getMetaMaskAccountsOrdered` and
`getOrderedConnectedAccountsForConnectedDapp` as input selectors. Since
`createSelector` forwards all arguments to input selectors, `activeTab`
continues to be passed correctly to
`getOrderedConnectedAccountsForConnectedDapp`.

```js
// Before
export function getUnconnectedAccounts(state, activeTab) {
  const accounts = getMetaMaskAccountsOrdered(state);
  const connectedAccounts = getOrderedConnectedAccountsForConnectedDapp(state, activeTab);
  return accounts.filter((account) =>
    !connectedAccounts.some((c) => c.address === account.address),
  );
}

// After
export const getUnconnectedAccounts = createSelector(
  getMetaMaskAccountsOrdered,
  getOrderedConnectedAccountsForConnectedDapp,
  (accounts, connectedAccounts) =>
    accounts.filter((account) =>
      !connectedAccounts.some((c) => c.address === account.address),
    ),
);
```

- **`ui/selectors/selectors.test.js`** — Adds a
`describe('getUnconnectedAccounts')` block covering: filtering connected
accounts out of results, returning all accounts when none are connected,
and returning an empty array when all accounts are connected.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Selector refactor with equivalent behavior and new unit tests; no
auth, security, or data-path changes.
> 
> **Overview**
> **Memoizes** `getUnconnectedAccounts` with `createSelector`, using
`getMetaMaskAccountsOrdered` and
`getOrderedConnectedAccountsForConnectedDapp` as inputs so the filtered
list keeps a stable reference when accounts and dapp permissions are
unchanged—reducing extra re-renders in the connections UI.
> 
> The filter logic is unchanged; the second argument (`activeTab` /
origin) still flows through to the connected-accounts input selector.
> 
> **Tests:** adds `getUnconnectedAccounts` coverage (partial connect,
none connected, all connected) and toggles Reselect
`inputStabilityCheck` off in the test file so dev-mode checks do not
fail on this suite.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
c7e5977. 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>
…uest` (#44132)

## **Description**

`handleSnapRequest` was a pure single-action passthrough to
`SnapController:handleRequest`. Rather than routing it through
`LegacyBackgroundApiService`, this binds the `getApi` entry directly to
`SnapController:handleRequest` via the controller messenger, and
repoints the three construction-time `handleRequest` hooks (used by
`forwardRequestToSnap` in the permissions-kernel snap setup) to the same
direct bind. The now-unused `handleSnapRequest` controller method is
removed. Behavior is unchanged: the action handler takes the same `args`
object the old method passed through.

## **Related issues**

Progresses: https://consensyssoftware.atlassian.net/browse/WPC-1094

## **Manual testing steps**

1. Open a dapp that triggers a snap RPC request (e.g. a snap name
resolution or snap home page).
2. Confirm the snap request resolves as before.

## **Screenshots/Recordings**

### **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**
> Pure refactor with equivalent messenger routing; no change to RPC args
or snap execution behavior.
> 
> **Overview**
> Removes the **`handleSnapRequest`** wrapper on `MetaMaskController`
and wires snap RPC handling straight to
**`SnapController:handleRequest`** through
`controllerMessenger.call.bind(...)`.
> 
> The same bound handler is used for the legacy **`getApi`**
`handleSnapRequest` entry and for the three **`forwardRequestToSnap`**
hooks in the permissions-kernel snap setup (execution permission
processing). Call sites still pass the same `args` object; only the
indirection through the controller method is gone.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
b815f87. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…updateNetworksList` (#44133)

## **Description**

Part of the WPC-418 effort to slim down `MetamaskController.getApi()`.

The `updateNetworksList` getApi entry was a thin pass-through over
`networkOrderController.updateNetworksList`, wrapped only in a
`try/catch` that logged and rethrew. Since the
`NetworkOrderController:updateNetworksList` messenger action already
exists (the method is in `MESSENGER_EXPOSED_METHODS`), the getApi entry
is now bound directly to that action via the controller messenger and
the redundant `MetamaskController` wrapper method is removed.

No behavior change for the client: the UI thunk still calls
`submitRequestToBackground('updateNetworksList', [chainIds])` with the
same argument shape.

Progresses: https://consensyssoftware.atlassian.net/browse/WPC-1096

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Progresses: https://consensyssoftware.atlassian.net/browse/WPC-1096

## **Manual testing steps**

1. Open the network list in the UI and reorder networks via drag and
drop.
2. Confirm the new order persists (state `orderedNetworkList` is
updated) after reload.

## **Screenshots/Recordings**

### **Before**

### **After**

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Thin routing refactor with no intended change to network ordering
logic; only error logging around the old wrapper is dropped.
> 
> **Overview**
> Part of slimming **`MetamaskController.getApi()`**,
**`updateNetworksList`** is no longer implemented as a
**`MetamaskController`** method that forwarded to
**`networkOrderController.updateNetworksList`** inside a log-and-rethrow
**`try/catch`**.
> 
> The background API entry is now
**`this.controllerMessenger.call.bind(...,
'NetworkOrderController:updateNetworksList')`**, matching other
controller actions already exposed on the messenger. Callers such as
**`submitRequestToBackground('updateNetworksList', [chainIds])`** should
still hit the same controller logic and argument shape; failures will
surface from the messenger path without the extra **`log.error`**
wrapper.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
1f5e890. 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**

On gas-sponsorship networks, Monad, hardware-wallet transactions fail
instantly with no device prompt:

`eth_sendRawTransaction: Invalid parameters: transaction could not be
decoded: not enough input to decode`

The `TransactionController` sets `isExternalSign = true` whenever a
transaction
is gas-sponsored, regardless of account type. That flag skips the
signing step,
so the device is never prompted and `rawTx` is never produced. EOA
accounts are
unaffected because the EIP-7702 relay submits on their behalf; hardware
wallets
cannot hold a 7702 delegation, so no relay catches the publish and an
empty
payload is sent.

<!--
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: disable gas sponsorship for hw wallets 

## **Related issues**

Fixes:
https://consensyssoftware.atlassian.net/browse/MUL-1947?atlOrigin=eyJpIjoiOTYzMGIyOWRjNTE2NDJhZWEwM2NmYTUzNGUwOGZjOGUiLCJwIjoiaiJ9
 
## **Manual testing steps**

1. Select a **hardware-wallet account** (not an EOA).
2. Initiate a send of a **small, sponsorship-eligible** amount of native
token
(stay under Monad's gas sponsorship cap; keep gas modest). *This matters
—
if the transaction is ineligible for sponsorship, the bug does not
reproduce
   and the fix cannot be verified.*
3. On the confirmation screen, confirm the transaction.
4. **Verify:** the hardware device prompts for signature (Ledger
displays the
   transaction / Trezor shows the review screen). This is the key fix —
   previously the transaction failed instantly with no device prompt.
5. Approve the transaction on the device.
6. **Verify:** the transaction submits successfully and lands on chain
(no
`transaction could not be decoded` error; a transaction hash is
returned).
7. **Non-regression (EOA):** switch to an EOA (HD/imported) account on
the same
network and send a transaction. Verify it is still gas-sponsored (the
"Paid
   by MetaMask" indicator appears / no native gas is deducted).

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches transaction confirm approval and gasless/external-sign
routing; wrong conditions could break EIP-7702 gas sponsorship for EOAs
or leave HW txs broken.
> 
> **Overview**
> Fixes **instant failures on gas-sponsored networks** (e.g. Monad) when
confirming with a **hardware wallet**: the device never prompted and
`eth_sendRawTransaction` failed with an undecodable transaction.
> 
> On confirm, `useTransactionConfirm` now clears **`isExternalSign`**
(and sponsorship flags already follow **`isGaslessSupported`**) whenever
gasless is **not** supported for the account/chain—not only when the
user opts out of sponsorship. Gas estimation can set `isExternalSign`
for any sponsored tx; leaving it on skips signing and sends an empty raw
tx when no EIP-7702 relay applies (typical for HW).
> 
> Tests cover clearing `isExternalSign` when gasless is unsupported vs
keeping it when gasless is supported; confirmation test fixtures accept
**`isExternalSign`**.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
cef323c. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
release: sync stable to main for version 13.38.0
## **Description**

This PR prevents Sentry event processing from recursively reporting
storage read failures. Sentry uses persisted state to determine
MetaMetrics participation when no in-memory snapshot is available; if
that persisted-state read failed, `PersistenceManager.get` reported the
failure to Sentry, which re-entered the same persisted-state read path.

The fix adds an optional `reportErrors` flag to persisted-state reads.
Normal reads still report storage failures by default, while Sentry's
analytics-state lookup disables reporting and falls back to backup/null
without causing another Sentry capture.

## **Changelog**

CHANGELOG entry: null

<!--
## **Related issues**

Fixes:
-->

## **Manual testing steps**

1. Run the extension from this branch.
2. Complete onboarding or unlock an existing test wallet.
3. Trigger an error report while the background is still initializing or
while persisted state is unavailable.
4. Verify the extension does not repeatedly capture the same storage
read failure.

<!--
## **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.

## Validation

- `yarn test:unit app/scripts/lib/sentry-get-state.test.ts
app/scripts/lib/setup-initial-state-hooks.test.ts
shared/lib/stores/persistence-manager.test.ts`
- `yarn lint:changed:fix`
- `git diff --check`

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches persistence error reporting and Sentry’s analytics consent
path; behavior change is narrowly scoped with defaults preserved, but
mis-wiring `reportErrors` could hide real storage read failures from
Sentry.
> 
> **Overview**
> Adds an optional **`reportErrors`** flag on persisted-state reads so
storage **`get`** failures can still be logged without always sending
**`captureException`** to Sentry.
> 
> **`PersistenceManager.get`** now accepts **`reportErrors`** (default
**`true`**); when **`false`**, read errors are logged but not reported.
**`getPersistedState`** forwards the same option, and
**`getAnalyticsState`** calls **`getPersistedState({ reportErrors: false
})`** so MetaMetrics lookups during Sentry event processing do not
re-trigger persisted reads that report back into Sentry.
> 
> Default behavior for normal wallet reads is unchanged
(**`reportErrors: true`**). Types and unit tests cover the hook wiring
and the no-capture path.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
e1140f3. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@metamask-ci

metamask-ci Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor
Builds ready [143f29b]
Deprecated Browserify fallback builds
⚡ Performance Benchmarks (Total: 🟢 14 pass · 🟡 7 warn · 🔴 3 fail)

Baseline (latest main): 8b02f4a | Date: 7/15/2026 | Pipeline: 29382949392 | Baseline logs

Metricschrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 srpButtonToSrpForm(p95) [CI log]🔴 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🔴 [CI log]

Regressions (🔴 3 failures)

Interaction Benchmarks · Samples: 5
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
confirmTx
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
🟡 bridge_search_token

📈 Results compared to the previous 5 runs on main

  • ↑ confirmTx/confirm_tx: +46%
  • ↑ confirmTx/tbt: +12%
  • ↑ confirmTx/total: +46%
  • ↓ bridgeUserActions/longTaskCount: -29%
  • ↓ bridgeUserActions/longTaskTotalDuration: -29%
  • ↓ bridgeUserActions/tbt: -29%
  • ↑ bridgeUserActions/inp: +15%
  • ↑ loadNewAccount/load_new_account: +94%
  • ↑ loadNewAccount/total: +94%
  • ↓ loadNewAccount/inp: -15%
  • ↓ loadNewAccount/fcp: -52%
  • ↑ loadNewAccount/lcp: +1329%
  • ↑ confirmTx/confirm_tx: +62%
  • ↓ confirmTx/longTaskCount: -100%
  • ↓ confirmTx/longTaskTotalDuration: -100%
  • ↓ confirmTx/longTaskMaxDuration: -100%
  • ↓ confirmTx/tbt: -100%
  • ↑ confirmTx/total: +62%
  • ↓ confirmTx/fcp: -47%
  • ↑ confirmTx/lcp: +1177%
  • ↑ bridgeUserActions/bridge_load_page: +143%
  • ↑ bridgeUserActions/bridge_load_asset_picker: +55%
  • ↑ bridgeUserActions/bridge_search_token: +213%
  • ↓ bridgeUserActions/longTaskCount: -100%
  • ↓ bridgeUserActions/longTaskTotalDuration: -100%
  • ↓ bridgeUserActions/longTaskMaxDuration: -100%
  • ↓ bridgeUserActions/tbt: -100%
  • ↑ bridgeUserActions/total: +191%
  • ↓ bridgeUserActions/fcp: -45%
  • ↑ bridgeUserActions/lcp: +1176%
Startup Benchmarks · Samples: 100
Benchmarkchrome-webpackfirefox-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
🟡 loadScripts
startupPowerUserHome
[Sentry log · main/release]
–🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • ↓ startupStandardHome/uiStartup: -31%
  • ↓ startupStandardHome/load: -31%
  • ↓ startupStandardHome/domContentLoaded: -31%
  • ↓ startupStandardHome/domInteractive: -22%
  • ↓ startupStandardHome/firstPaint: -23%
  • ↓ startupStandardHome/backgroundConnect: -31%
  • ↓ startupStandardHome/firstReactRender: -30%
  • ↓ startupStandardHome/initialActions: -29%
  • ↓ startupStandardHome/loadScripts: -31%
  • ↓ startupStandardHome/setupStore: -29%
  • ↓ startupStandardHome/numNetworkReqs: -23%
  • ↓ startupStandardHome/longTaskCount: -29%
  • ↓ startupStandardHome/longTaskTotalDuration: -36%
  • ↓ startupStandardHome/longTaskMaxDuration: -32%
  • ↓ startupStandardHome/tbt: -38%
  • ↓ startupStandardHome/inp: -18%
  • ↓ startupStandardHome/fcp: -30%
  • ↓ startupStandardHome/lcp: -49%
  • ↑ startupStandardHome/domInteractive: +74%
  • ↑ startupStandardHome/fcp: +58%
  • ↑ startupPowerUserHome/uiStartup: +16%
  • ↑ startupPowerUserHome/load: +15%
  • ↑ startupPowerUserHome/domContentLoaded: +15%
  • ↑ startupPowerUserHome/domInteractive: +17%
  • ↑ startupPowerUserHome/backgroundConnect: +30%
  • ↑ startupPowerUserHome/firstReactRender: +12%
  • ↑ startupPowerUserHome/initialActions: +11%
  • ↑ startupPowerUserHome/loadScripts: +14%
  • ↓ startupPowerUserHome/setupStore: -37%
  • ↑ startupPowerUserHome/inp: +43%
  • ↑ startupPowerUserHome/lcp: +12%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 startupPowerUserHome/INP: p75 264ms
  • 🟡 startupPowerUserHome/LCP: p75 3.6s
User Journey Benchmarks · Samples: 5 · real API 🔴 3
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 [CI log]
🔴 doneButtonToHomeScreen
🔴 total
🔴 [CI log]
🟡 doneButtonToHomeScreen
🔴 total
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🔴 [CI log]
🔴 total
assetDetails
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
importSrpHome
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
sendTransactions
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
swap
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • ↑ onboardingImportWallet/srpButtonToSrpForm: +19%
  • ↑ onboardingImportWallet/confirmSrpToPwForm: +13%
  • ↑ onboardingImportWallet/pwFormToMetricsScreen: +13%
  • ↑ onboardingImportWallet/metricsToWalletReadyScreen: +57%
  • ↓ onboardingImportWallet/doneButtonToHomeScreen: -38%
  • ↓ onboardingImportWallet/longTaskCount: -27%
  • ↓ onboardingImportWallet/longTaskTotalDuration: -17%
  • ↓ onboardingImportWallet/total: -35%
  • ↓ onboardingNewWallet/doneButtonToAssetList: -14%
  • ↑ onboardingNewWallet/longTaskCount: +18%
  • ↓ onboardingNewWallet/longTaskMaxDuration: -50%
  • ↓ onboardingNewWallet/tbt: -30%
  • ↓ onboardingNewWallet/total: -12%
  • ↑ solanaAssetDetails/assetClickToPriceChart: +43%
  • ↑ solanaAssetDetails/total: +43%
  • ↑ solanaAssetDetails/inp: +32%
  • ↑ importSrpHome/openAccountMenuAfterLogin: +27%
  • ↓ importSrpHome/homeAfterImportWithNewWallet: -14%
  • ↓ importSrpHome/longTaskCount: -14%
  • ↓ importSrpHome/total: -13%
  • ↓ importSrpHome/cls: -29%
  • ↑ sendTransactions/openSendPageFromHome: +139%
  • ↑ sendTransactions/reviewTransactionToConfirmationPage: +166%
  • ↑ sendTransactions/longTaskCount: +25%
  • ↑ sendTransactions/longTaskTotalDuration: +31%
  • ↑ sendTransactions/longTaskMaxDuration: +35%
  • ↑ sendTransactions/tbt: +59%
  • ↑ sendTransactions/total: +153%
  • ↓ sendTransactions/inp: -15%
  • ↓ swap/longTaskCount: -17%
  • ↑ swap/tbt: +17%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 importSrpHome/INP: p75 320ms
  • 🟡 solanaAssetDetails/FCP: p75 2.0s
  • 🟡 importSrpHome/INP: p75 208ms
  • 🟡 importSrpHome/FCP: p75 2.1s
  • 🟡 sendTransactions/FCP: p75 2.0s
  • 🟡 swap/FCP: p75 2.0s
  • 🟡 swap/LCP: p75 2.5s
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]
Bundle sizes
  • background: 14.22 MiB
  • ui: 17.06 MiB
  • common: 0 Bytes
  • other: 998.07 KiB
  • contentScripts: 1.87 MiB
  • zip: 27.03 MiB
No matching bundle-size baseline was found in the history data, so diff values are omitted.

🍒 What's in this RC

Cherry-picks (171 commits)
Commit Description
143f29b8b4 release(runway): cherry-pick chore: reduce Sentry trace sampling cp-13.40.0 (#44462)
5d2bd7df70 release(runway): cherry-pick fix(sentry): Resolve AggregatedBalanceSelector transaction volume spike by not passing trace into getAggregatedBalanceForAccount cp-13.40.0 (#44460)
b040e51865 Merge branch 'stable' into release/13.40.0
8d99e9d5bb release(runway): cherry-pick chore: bump @metamask/tron-wallet-snap to ^1.31.0 cp-13.40.0 (#44428)
795203820e release: release-changelog/13.40.0 (#44327)
4dd7e83388 Merge branch 'stable' into release/13.40.0
55c0123941 release(runway): cherry-pick fix: extra pending row from local state cp-13.40.0 (#44370)
2c1234d055 release(runway): cherry-pick fix(assets): restore google.svg and relocate to app/images/ cp-13.40.0 (#44391)
bcb2b82445 release: changelog
73c875a3f6 refactor(analytics): migrate multichain chrome events (#43900)
84145c408f fix: mv3 sw lavamoat background wrapping (#44187)
3d173df60c fix(token-management): seed unified assets for non-EVM search imports cp-13.39.1 cp-13.40.0 (#44361)
a886918443 feat(ramps): add ramps controller hooks and selectors (#43963)
942441b93f fix: Fix Firefox detatched-window memory leak by avoiding DocumentPictureInPicture instantiation in Snow hook cp-13.39.2 (#44352)
a7485c7561 feat: support Robinhood chain on swaps cp-13.39.1 (#44347)
22c457ff91 chore: update CODEOWNERS for engagement team (#44336)
4e65bd74c9 chore: bump @metamask/profile-sync-controller to ^28.3.0 (#44344)
838c70370b fix(rewards): retry silent auth when remote flags hydrate after onboarding (#44282)
c93e5a143c refactor: migrate musd convert toast (#44206)
09d105c0bd feat: add Robinhood Infura RPC + assets ctrl bump cp-13.39.1 (#44331)
c1860fc58d fix(release): pin firefox bundle.sh per release tag (INFRA-3753) (#44121)
f0d9f25e2e refactor: consolidate Home page into single hook-based component (#44293)
b1158f292b feat(ramps): wire RampsController into background (#43962)
d3fe41296a fix: copy fixes for musd convert and perps cp-13.40.0 (#44332)
deaf6f0e86 chore: migrate captureTestError to LegacyBackgroundApiService (#44350)
9b3401b39e chore: onboarding Terms of Usage and Privacy Link e2e (#44323)
850b14df49 chore: migrate decodeTransactionData to LegacyBackgroundApiService (#44242)
f84631829d feat(notifications): include app version in push registration metadata (#43605)
f9c195294f chore: migrate isRelaySupported to LegacyBackgroundApiService (#44238)
b2b0f6b947 feat(hardware-wallets): add signing page copy and utilities (#43942)
9eeae6c1e0 feat(e2e): add Tron local node bootstrap (#44151)
4dac656a96 fix(confirmations): align warning icon inline with label in estimated changes section (#44207)
29435c41e6 feat(ci): verify release attestation before CWS upload (INFRA-3661) (#44123)
0eb7b6df11 feat(ci): attest webpack release zips at publish (INFRA-2665) (#44122)
521383313d refactor: address wallet-init review nits (#44116)
6d8b527c93 feat: extract Stellar asset activation UI component (#44193)
864daacd24 feat: show QR code for trending/explore deeplink instead of routing home (#44170)
2944262403 chore: add tooltips to order labels (#44290)
7ec2719d8b chore: resolve toast implementation (#44292)
0f840878ff release: Bump main version to 13.41.0 (#44328)
823e0a0eb9 Merge pull request #44325 from MetaMask/stable-main-13.39.0
f9bad587cc Merge origin/main into stable-main-13.39.0
0b5a203bd9 chore: deprecate old toast component (#44275)
9d4d19b5c5 feat: scrollable tab (#44316)
ad6f7bb54f feat(perps): gate full asset names behind perpsShowFullAssetNames flag cp-13.39.0 (#44304)
970a0c6a75 chore: migrate checkDelegationDisabled to LegacyBackgroundApiService (#44266)
ea6632be11 feat(networks): add Robinhood Chain as featured network (#44310)
3d8272de95 chore: update CODEOWNERS for money-movement team (#44314)
2b74a1ae0a refactor(analytics): migrate home activity and wallet overview events (#43899)
ed6e1a4a68 feat: added warning banner (#44309)
ba6e32f5b4 feat(engagement): Port deeplink bypass by route feature from mobile to extension (#43639)
b77923c40d chore: update transaction id copied translation (#44313)
b8921b2220 feat: upgrade notifications service controller to support v4 api (#44263)
db9e57370c feat: bump Tron snap 1.29.1 (#44306)
ea2c5e6415 perf(6915): memoize getApprovalFlows Selector (#44224)
7c2231cb17 feat: show complete onboarding screen only once (#44232)
ad91394089 refactor(analytics): migrate confirmations events (#43892)
5d65e7a8dc refactor(analytics): migrate swaps and bridge events (#43891)
11fb25664e chore: migrate isSendBundleSupported to LegacyBackgroundApiService (#44240)
104ef3781d test(e2e): add BTC activity cluster spec (#43005)
7a647f51f8 feat(hardware-wallets): add signing page components (#43941)
13663f6db8 refactor: add TransactionController to wallet initialization (#43182)
7820bf530c chore: migrate getPhishingResult to LegacyBackgroundApiService (#44255)
c15b8dbeee refactor(analytics): migrate perps events (#43890)
4d33ee059f chore: migrate throwTestError to LegacyBackgroundApiService (#44239)
94614aba0f chore: migrate getAssets to LegacyBackgroundApiService (#44241)
4a9c03cbeb fix(perps): hide perps balance and position data when privacy mode is enabled (#44262)
93e14da37f fix: updated added to chainlist icon and padding (#44268)
480d4f821e fix: arc swap assets picker missing prices (#44073)
5825f03d69 feat(perps): gate terminal backend behind perpsTerminalBackendEnabled feature flag cp-13.39.0 (#43989)
03230d6229 test: fix flaky test MetaMask onboarding User can add custom network during onboarding (#44243)
5652b6cb1e feat(stellar): add trustline support in transaction history v3 (#44200)
d5ccb0e794 chore(e2e): scaffold bitcoin-regtest-up bootstrap for BTC E2E (#42943)
2ea4542077 fix: transaction id row (#44188)
aa5378721b fix: swap tx fails when smart account upgrade is required cp-13.39.0 (#44291)
a85e8a0380 chore: remove unused selectors (#44278)
de7420417a Merge pull request #44272 from MetaMask/stable-main-13.38.1
7c3e420839 chore(component-library): remove unused legacy icon SVGs (#44227)
698a384cbb fix(ramps): remove network gating from buy entry points (#44069)
7f534c5cda chore: New Crowdin Translations by GitHub Action cp-13.39.0 (#43689)
e07fedcb92 Merge origin/main into stable-main-13.38.1
33acc092d8 chore: upgrade design system packages (v52.0.0) (#44226)
83378bca32 perf(6556): remove redundant isEqual from awaiting-signatures useSelector calls (#44234)
4d12b0cc00 feat: added transition for settings page (#44074)
65c0fca156 fix(perps): truncate long asset names in market list to a single line cp-13.39.0 (#44214)
04afd3c489 perf: replace deep equality with shallow + add result equality to filter-based transaction selectors (#44110)
ecaa92746c perf(6916): refactor core UX selectors to remove deep-equality subscriptions (#44235)
0be73a9e7a fix(onboarding): updated min-height for login-option cp-13.39.0 (#44265)
9ef5547abe bump: upgrade @metamask/assets-controller to ^10.1.0 (#44246)
38571fa64d refactor(analytics): move event enrichment downstream (#44219)
da8373fef1 feat: use canonical_profile_id as a segment trait instead of profile_id (#44213)
af45d23d92 refactor(analytics): migrate multichain accounts events (#43896)
523715f346 feat(musd): tag prefilled_max input type on Transaction Added event (#44211)
0eab632cb3 chore: bind updateHiddenAccountsList directly to AccountOrderController:updateHiddenAccountsList (#44245)
3fb4d44298 chore: bind updateAccountsList directly to AccountOrderController:updateAccountsList (#44244)
0c644a4a55 chore: remove unused endTrace from getApi (#44237)
89add44149 chore: migrate toggleExternalServices to LegacyBackgroundApiService (#44143)
d4ce5e48ab chore(assets): add robinhood svg (#44191)
787b18b802 feat: Bump Snaps packages (#44210)
4253ff3e2e chore(6928): Replace react-beautiful-dnd with @hello-pangea/dnd (#43328)
8f9719a7d9 refactor(analytics): migrate smart transactions controller events (#43902)
2f843003ed feat(e2e): add Tron seeder asset helpers (#44150)
a93e640377 chore: removed old token import modal (#43712)
3d60c993a6 test: enhance clikElementSafe (#44236)
c4933e235a refactor(analytics): migrate multichain account chrome events (#43919)
fbd638ea2c refactor(analytics): migrate accounts hardware wallet events (#43895)
da0bbb6375 fix: disable CTA swap button for Tron when no network fees retrieved (#44107)
6639fdb7c8 fix: bignumber issues everywhere cp-13.38.1 (#44216)
ee138ca34d feat: scam questionnaire on malicious internal send flows (#43822)
c1bbdd9676 refactor(analytics): migrate token management assets events (#43912)
44008b9886 feat(e2e): add java-tron local node configuration (#44149)
a5ebebb3b0 feat: replace use metametrics with useAnalytics hook for networks page (#44212)
e53335e0c7 chore: set bottom nav bar conditional rendering (#44215)
82846bc6a1 feat: added BFT consolidation feature for new users (#43935)
8f31233a4f refactor(analytics): migrate assets events (#43889)
6dc7a8dad8 chore: bind alignMultichainWallets directly to MultichainAccountService:alignWallets (#44134)
09a4ab422b refactor(hardware-wallets): unify signing tracker (#43940)
1a2ca55143 chore: remove unused trackInsightSnapView from getApi (#44135)
d063aa9af5 chore: bump assets controller to v10.0.0 ASSETS-3385 (#44055)
f4819cfd9c chore: bump @metamask/bitcoin-wallet-snap to ^1.14.2, @metamask/solana-wallet-snap to ^2.10.0 (#44209)
fdd45f6033 refactor(analytics): migrate network and navigation chrome events (#43918)
c9b563c309 refactor(analytics): migrate modals and name display events (#43917)
3b6129124e refactor(analytics): migrate unlock and rewards events (#43916)
09da33f257 feat(e2e): add shared local node fixture plumbing (#44148)
ff56170604 test: Sync Feature Flag Registry - 2026-07-07 01:33 UTC (#44204)
cf8762c11f feat: sync wallets/accounts via MWP QR (#43711)
f23dee8a95 feat: Add UI components for Ledger status screens (#43720)
efd4b3f69d chore: clean up legacy Tag storybook (#44186)
1f603c3ba2 fix(confirmations): show Pay with row on initial MM Pay page (#44190)
481a27f030 feat(stellar): add Stellar chain utilities (#44192)
fa3a49e3f7 ci: make check-template-and-add-labels.mts run in Node 24 (#44056)
767bc86afe fix(swaps): fix stale search results after network filter change cp-13.39.0 (#44194)
0cd68d537a ci: fix "All jobs pass" in cross-repo PRs (#44182)
34e80bb6d1 feat: create bottom bar UI (#44197)
5125b602a9 perf(6645): refactor feature-specific selectors in home.component (#43577)
ba8bb54199 test: update wallet-fixture-export.spec.ts to the latest state and prevent drift with wallet-fixture-validation.spec.ts (#44127)
6aab821565 refactor(analytics): migrate keychain and SRP events (#43897)
5e03105fad test(e2e): add BTC assets cluster spec (#43006)
4821f0d027 refactor(analytics): migrate platform library background events (#43920)
d1ce52bc0f refactor(analytics): migrate core platform background events (#43901)
d7b3a92f70 test(e2e): cover completing a BTC to USDC (ERC20) swap (#43834)
3924472a09 fix: prevent Sentry storage read recursion (#44057)
5f73f93b46 Merge pull request #44172 from MetaMask/stable-main-13.38.0
1eb7182a53 Merge origin/main into stable-main-13.38.0
dd7c20db7e fix: disable gas sponsorship for hw wallets cp 13.39.0 (#44144)
f68939ba26 chore: bind updateNetworksList directly to NetworkOrderController:updateNetworksList (#44133)
21b8d0c67d chore: bind handleSnapRequest directly to SnapController:handleRequest (#44132)
37ddaa468a perf: memoize getUnconnectedAccounts selector (#44109)
75730ef0cd test: fix flaky test Ledger Hardware unlocks multiple accounts at once and removes one (#44094)
e5ee1c4b21 chore: setup codeownership of metamask-controller (#44131)
a4d0a59d15 chore: use delay on the global spinner (#44120)
cd82cd4c09 test: fix update-fixtures due to github policy change on actions cache (#44128)
72a4b94be4 refactor(analytics): migrate backup and sync account events (#43915)
535522dab6 chore: move aus e2e mocks out of auth CO scope (#44106)
a2014674f6 refactor(analytics): migrate shield and subscription events (#43893)
69c2aa4135 refactor(analytics): migrate onboarding welcome events (#43914)
a01132e83a refactor(analytics): migrate onboarding flow events (#43894)
63e37788f6 feat: source AddressBookController from @metamask/wallet@6.0.0 (#44112)
09dc5d616e refactor: remove deprecated "turn on notifications" modal (#44098)
3215860c6e chore: bind createNextMultichainAccountGroup directly to MultichainAccountService:createNextMultichainAccountGroup (#44103)
90f149a51a feat(swaps): integrate bridge QuoteStatusManager behind feature flag cp-13.39.0 (#44006)
a1c57e10d3 feat: update rbtc rootstock native icon (#44115)
c150be98df feat: add React Refresh to webpack watch builds (#43703)
184edd940c test: add automated RC build workflow for Extension, aligned with Mobile's workflow, aligns Extension RC notifications with Mobile (#42960)
d98ee34687 chore: upgrade design system packages (v50.0.0) (#44090)
3413101307 release: Bump main version to 13.40.0 (#44119)
8023b3c7f2 fix: bignumber incident 1752 cp-13.38.0 (#44097)
1c43659138 refactor(analytics): migrate send flow confirmation metrics (#43913)
8951ee1d47 refactor(analytics): migrate settings and privacy events (#43898)
b374c83130 refactor(analytics): migrate earn/mUSD events (#43888)
58c79c4cba test: fix update-fixtures script permissions (#44111)

Changelog (8 commits from main at RC cut)
Commit Description
27ee2a2b77 Merge pull request #44395 from MetaMask/release/13.39.2
311d329644 Merge branch 'stable' into release/13.39.2
19c20c50b9 Merge pull request #44342 from MetaMask/release/13.39.1
52e9d05e7c release: release-changelog/13.39.2 (#44394)
383e8dfbe9 fix: mv3 sw lavamoat background wrapping (#44187) (#44402)
c7383581ac release(runway): cherry-pick fix: Fix Firefox detatched-window memory leak by avoiding DocumentPictureInPicture instantiation in Snow hook cp-13.39.2 (#44401)
dab19fc117 bump semvar version to 13.39.2
05052d192c Merge pull request #44117 from MetaMask/release/13.39.0

AI Test Plan

Risk Score High Risk Medium Risk Files Changed Commits
54/100 5 9 1313 187
Cherry-Pick Scenarios (4)

High Risk Scenarios (1)

1. Activity List – Duplicate Pending Rows

Risk Level: HIGH

Why This Matters: Cherry-pick 44370 fixes duplicate pending rows from local state; duplicates mislead users about transaction status and can cause erroneous retries.

Test Steps:

  1. Send a transaction and keep it pending (e.g., set low gas); open the Activity tab and observe entries.
  2. Ensure only one pending row appears for the transaction; refresh the extension and confirm no duplicates.
  3. Speed up or cancel the transaction; verify the Activity view transitions cleanly (replaced/canceled) with no ghost or extra rows.

Medium Risk Scenarios (3)

1. Featured Networks – Robinhood Chain

Risk Level: MEDIUM

Why This Matters: Cherry-pick 44346 adds Robinhood Chain as a featured network; misconfiguration (chainId/RPC/explorer) can break switching and confuse users.

Test Steps:

  1. Open Add network > Featured and add Robinhood Chain; confirm the add and switch complete without errors.
  2. Verify network details: name, chain ID, currency symbol, RPC URL, and block explorer links (e.g., View account in explorer) are correct and responsive.
  3. Switch back and forth between Robinhood Chain and another network; confirm account/address display and Assets list load correctly.

2. Token Management – Non-EVM Search Imports (Unified Assets)

Risk Level: MEDIUM

Why This Matters: Cherry-pick 44361 seeds unified assets for non-EVM search imports; without this, users may fail to find or add popular non-EVM assets.

Test Steps:

  1. Connect/enable a supported non-EVM network (e.g., Tron via its Snap), then open the Import tokens/coins flow for that network.
  2. Search for a common non-EVM asset (e.g., USDT on Tron) and confirm results appear with correct symbol and icon.
  3. Add the asset; verify it appears in the Assets list with correct decimals and balance fetches without error.

3. Balances – AggregatedBalanceSelector Stability

Risk Level: MEDIUM

Why This Matters: Cherry-pick 44460 reduces tracing in AggregatedBalanceSelector to stop a transaction volume spike; it must not destabilize or misreport balances.

Test Steps:

  1. With multiple accounts holding many assets, open the Assets/Portfolio view and observe total balances.
  2. Rapidly switch accounts and networks; confirm totals remain stable with no transient spikes or flicker.
  3. Leave the view open for 1–2 minutes; ensure no periodic jumps in displayed totals occur.

Release Scenarios (10)

High Risk Scenarios (4)

1. State Migrations (Migration 216)

Risk Level: HIGH

Why This Matters: State migrations can corrupt or drop user data; verifying upgrade paths ensures accounts, networks, and assets remain intact after migration 216.

Test Steps:

  1. Start with a 13.39.x profile containing: 2+ accounts (one imported SRP, one hardware), at least one custom network, and several imported tokens.
  2. Upgrade the same profile to 13.40.0 and open the extension; let it complete startup.
  3. Verify all accounts and custom networks are present; token lists and balances load without errors.
  4. Open Activity and Assets tabs for each account to confirm history and totals still display correctly.
  5. Send a small native transfer on a known network to confirm post-migration transactions work end-to-end.

2. Seedless Onboarding (Migration/Resume behavior)

Risk Level: HIGH

Why This Matters: Changes to seedless onboarding migrations can strand users mid-flow or create unusable accounts; resuming and completing must be reliable.

Test Steps:

  1. On 13.39.x, begin seedless (passkey) onboarding and stop midway (e.g., after creating credentials but before final confirmation).
  2. Upgrade to 13.40.0 and reopen the extension; resume the onboarding flow.
  3. Complete onboarding and land on the wallet; verify the created account is usable (copy address, view QR).
  4. Lock and unlock; sign a test message to confirm the account functions normally post-resume.

3. Transaction Flow (Send/Speed Up/Cancel)

Risk Level: HIGH

Why This Matters: Core controller and UI changes can subtly break confirmation flows, status transitions, or gas handling; ensuring send/speed up/cancel work prevents loss or confusion.

Test Steps:

  1. On Ethereum Mainnet, send a small ETH transfer from Account 1 to Account 2 and confirm.
  2. While pending, use Speed Up with a higher gas setting and confirm the replacement; verify the status updates correctly.
  3. On an L2 (e.g., Base), send an ERC-20 transfer; open Advanced gas/options if available and confirm the transaction.
  4. Initiate another send, then Cancel it; verify the Activity list reflects a canceled entry without lingering or duplicate rows.

4. MetaMetrics Consent and Privacy Controls

Risk Level: HIGH

Why This Matters: Significant analytics controller changes can regress privacy guarantees; user consent must be honored and preferences must persist.

Test Steps:

  1. Fresh install: at the MetaMetrics prompt, choose to opt out; complete onboarding.
  2. Perform common actions (switch networks, open Settings, initiate a send) and confirm no additional telemetry prompts or nags reappear.
  3. In Settings > Security & privacy, toggle MetaMetrics on; reload the extension and confirm the preference persists.
  4. Toggle back off; perform a transaction and ensure no new prompts appear.

Medium Risk Scenarios (6)

1. Assets List Sorting and Control Bar

Risk Level: MEDIUM

Why This Matters: Refactors to assets list and control bar can break ordering, persistence, or filtering, degrading discoverability and trust in balances.

Test Steps:

  1. Open Assets and change sorting to Highest value, then Name A–Z, then by Balance; toggle ascending/descending where available.
  2. Confirm the list reorders correctly for each option and sorting is applied consistently across accounts.
  3. Close and reopen the extension; ensure the last sorting preference persists.
  4. Use search/filter in the control bar, verify results update, then clear filters to restore the full list.

2. Asset Inactive Badge and Warnings

Risk Level: MEDIUM

Why This Matters: New UI indicators for inactive assets must inform without blocking legitimate actions; incorrect badges erode user confidence.

Test Steps:

  1. Import a token that is flagged as inactive/delisted via the token import flow.
  2. Verify an Inactive badge appears in the asset row and detail view with appropriate warning text.
  3. Attempt to initiate a send from the inactive token; ensure warnings appear but the flow remains usable if allowed.
  4. Remove the token and confirm the asset list updates with no residual inactive indicators.

3. DeFi List Empty State and Protocol Cells

Risk Level: MEDIUM

Why This Matters: UI changes to DeFi cells and empty states can cause broken rendering or confusing states, impacting portfolio usability.

Test Steps:

  1. With an account that has no DeFi positions, open the DeFi tab and confirm the empty state renders correctly.
  2. Switch networks and accounts; ensure the empty state and any protocol cells render without layout jumps or missing strings.
  3. If any protocol entries appear, open a protocol cell and verify details populate and navigation works.

4. Onboarding Variants (SRP, Create New, Hardware)

Risk Level: MEDIUM

Why This Matters: Onboarding method action type changes can break specific paths; ensuring each path completes avoids onboarding lockouts.

Test Steps:

  1. Fresh profile: complete Import using Secret Recovery Phrase; verify you land in the wallet with the expected address.
  2. Fresh profile: complete Create a new wallet; confirm SRP reveal works and the account is created.
  3. Connect a hardware wallet (Ledger/Trezor), add an account, and verify the address and balances display without errors.

5. Portfolio/Total Balance Aggregation

Risk Level: MEDIUM

Why This Matters: Controller changes around balance selection can cause incorrect totals or UI instability, leading to user mistrust of displayed balances.

Test Steps:

  1. Use 3+ accounts each holding several assets across at least two EVM networks; open the Assets/Portfolio view.
  2. Switch between accounts rapidly and scroll the list; verify totals update smoothly with no flicker or sudden spikes.
  3. Toggle any available options (e.g., hide small balances) and confirm totals recompute correctly.

6. Localization Sanity (Amharic/Arabic)

Risk Level: MEDIUM

Why This Matters: Recent locale string changes can surface missing or broken translations on key screens, degrading usability for non-English users.

Test Steps:

  1. In Settings > General, switch language to Amharic and navigate Home, Send, and Settings screens.
  2. Repeat in Arabic; verify there are no missing keys (e.g., untranslated placeholders) or broken layouts.
  3. Switch back to English and confirm UI returns to expected text without residual formatting issues.

Teams Sign-off Status

Signed off: None yet

Awaiting sign-off (5):
Assets, Networks, Onboarding, Security, Transactions


Generated by AI Test Plan Analyzer (gpt-5) at 2026-07-15T02:31:45.662Z

AI generated test plan (JSON): test-plan-13.40.0.json

…b Action cp-13.40.0 (#44469)

- chore: New Crowdin Translations by GitHub Action cp-13.40.0 (#44329)

Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
[ccadeee](ccadeee)

Co-authored-by: MetaMask Bot <37885440+metamaskbot@users.noreply.github.com>
Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
@metamask-ci

metamask-ci Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor
Builds ready [1ae883a]
Deprecated Browserify fallback builds
⚡ Performance Benchmarks (Total: 🟢 10 pass · 🟡 11 warn · 🔴 3 fail)

Baseline (latest main): 56e0cbf | Date: 7/15/2026 | Pipeline: 29430950598 | Baseline logs

Metricschrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 longTaskCount(p95) [CI log]🔴 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🔴 [CI log]

Regressions (🔴 3 failures)

Interaction Benchmarks · Samples: 5
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
🔴 load_new_account
confirmTx
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
🔴 bridge_load_page

📈 Results compared to the previous 5 runs on main

  • ↑ loadNewAccount/inp: +17%
  • ↑ loadNewAccount/lcp: +25%
  • ↑ confirmTx/confirm_tx: +44%
  • ↑ confirmTx/total: +44%
  • ↑ confirmTx/fcp: +40%
  • ↑ confirmTx/lcp: +75%
  • ↑ bridgeUserActions/bridge_load_page: +43%
  • ↓ bridgeUserActions/longTaskCount: -29%
  • ↓ bridgeUserActions/longTaskTotalDuration: -25%
  • ↓ bridgeUserActions/tbt: -22%
  • ↓ bridgeUserActions/inp: -17%
  • ↑ bridgeUserActions/fcp: +16%
  • ↑ loadNewAccount/load_new_account: +823%
  • ↑ loadNewAccount/total: +823%
  • ↓ loadNewAccount/inp: -22%
  • ↑ loadNewAccount/lcp: +1231%
  • ↑ confirmTx/confirm_tx: +62%
  • ↓ confirmTx/longTaskCount: -100%
  • ↓ confirmTx/longTaskTotalDuration: -100%
  • ↓ confirmTx/longTaskMaxDuration: -100%
  • ↓ confirmTx/tbt: -100%
  • ↑ confirmTx/total: +62%
  • ↑ confirmTx/fcp: +17%
  • ↑ confirmTx/lcp: +1346%
  • ↑ bridgeUserActions/bridge_load_page: +2078%
  • ↑ bridgeUserActions/bridge_load_asset_picker: +182%
  • ↓ bridgeUserActions/longTaskCount: -100%
  • ↓ bridgeUserActions/longTaskTotalDuration: -100%
  • ↓ bridgeUserActions/longTaskMaxDuration: -100%
  • ↓ bridgeUserActions/tbt: -100%
  • ↑ bridgeUserActions/total: +212%
  • ↑ bridgeUserActions/fcp: +16%
  • ↑ bridgeUserActions/lcp: +1215%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 loadNewAccount/FCP: p75 1.9s
  • 🟡 confirmTx/FCP: p75 2.3s
  • 🟡 bridgeUserActions/FCP: p75 1.9s
  • 🟡 loadNewAccount/FCP: p75 1.9s
  • 🟡 confirmTx/FCP: p75 1.9s
  • 🟡 bridgeUserActions/FCP: p75 1.9s
Startup Benchmarks · Samples: 100
Benchmarkchrome-webpackfirefox-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
startupPowerUserHome
[Sentry log · main/release]
–🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • ↑ startupStandardHome/setupStore: +12%
  • ↑ startupStandardHome/domInteractive: +25%
  • ↑ startupStandardHome/initialActions: +11%
  • ↑ startupStandardHome/fcp: +26%
  • ↓ startupPowerUserHome/uiStartup: -34%
  • ↓ startupPowerUserHome/load: -29%
  • ↓ startupPowerUserHome/domContentLoaded: -28%
  • ↓ startupPowerUserHome/backgroundConnect: -42%
  • ↓ startupPowerUserHome/firstReactRender: -26%
  • ↑ startupPowerUserHome/initialActions: +11%
  • ↓ startupPowerUserHome/loadScripts: -29%
  • ↓ startupPowerUserHome/setupStore: -92%
  • ↓ startupPowerUserHome/inp: -35%
  • ↓ startupPowerUserHome/lcp: -34%
User Journey Benchmarks · Samples: 5 · real API 🔴 3
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 [CI log]
🔴 doneButtonToHomeScreen
🔴 total
🔴 [CI log]
🔴 total
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🔴 [CI log]
🔴 total
assetDetails
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
importSrpHome
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
sendTransactions
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
swap
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • ↓ onboardingImportWallet/srpButtonToSrpForm: -12%
  • ↓ onboardingImportWallet/confirmSrpToPwForm: -21%
  • ↓ onboardingImportWallet/pwFormToMetricsScreen: -15%
  • ↓ onboardingImportWallet/metricsToWalletReadyScreen: -11%
  • ↓ onboardingImportWallet/doneButtonToHomeScreen: -11%
  • ↓ onboardingImportWallet/openAccountMenuToAccountListLoaded: -31%
  • ↓ onboardingImportWallet/longTaskMaxDuration: -22%
  • ↓ onboardingImportWallet/tbt: -18%
  • ↑ onboardingNewWallet/srpButtonToPwForm: +11%
  • ↓ onboardingNewWallet/doneButtonToAssetList: -14%
  • ↓ onboardingNewWallet/longTaskCount: -29%
  • ↓ onboardingNewWallet/longTaskTotalDuration: -37%
  • ↓ onboardingNewWallet/longTaskMaxDuration: -12%
  • ↓ onboardingNewWallet/tbt: -49%
  • ↓ onboardingNewWallet/total: -10%
  • ↑ solanaAssetDetails/assetClickToPriceChart: +30%
  • ↑ solanaAssetDetails/total: +30%
  • ↓ solanaAssetDetails/lcp: -13%
  • ↑ importSrpHome/openAccountMenuAfterLogin: +115%
  • ↓ importSrpHome/homeAfterImportWithNewWallet: -41%
  • ↓ importSrpHome/longTaskCount: -12%
  • ↓ importSrpHome/total: -37%
  • ↓ importSrpHome/cls: -50%
  • ↑ swap/openSwapPageFromHome: +37%
  • ↓ swap/longTaskCount: -20%
  • ↓ swap/longTaskTotalDuration: -12%
  • ↑ swap/longTaskMaxDuration: +25%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 importSrpHome/INP: p75 360ms
  • 🟡 solanaAssetDetails/FCP: p75 2.0s
  • 🟡 importSrpHome/FCP: p75 1.9s
  • 🟡 sendTransactions/FCP: p75 2.0s
  • 🟡 sendTransactions/LCP: p75 2.5s
  • 🟡 swap/FCP: p75 2.0s
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]
Bundle sizes
  • background: 14.22 MiB
  • ui: 17.06 MiB
  • common: 0 Bytes
  • other: 998.07 KiB
  • contentScripts: 1.87 MiB
  • zip: 27.07 MiB
No matching bundle-size baseline was found in the history data, so diff values are omitted.

🍒 What's in this RC

Cherry-picks (172 commits)
Commit Description
1ae883ad69 release(runway): cherry-pick chore: New Crowdin Translations by GitHub Action cp-13.40.0 (#44469)
143f29b8b4 release(runway): cherry-pick chore: reduce Sentry trace sampling cp-13.40.0 (#44462)
5d2bd7df70 release(runway): cherry-pick fix(sentry): Resolve AggregatedBalanceSelector transaction volume spike by not passing trace into getAggregatedBalanceForAccount cp-13.40.0 (#44460)
b040e51865 Merge branch 'stable' into release/13.40.0
8d99e9d5bb release(runway): cherry-pick chore: bump @metamask/tron-wallet-snap to ^1.31.0 cp-13.40.0 (#44428)
795203820e release: release-changelog/13.40.0 (#44327)
4dd7e83388 Merge branch 'stable' into release/13.40.0
55c0123941 release(runway): cherry-pick fix: extra pending row from local state cp-13.40.0 (#44370)
2c1234d055 release(runway): cherry-pick fix(assets): restore google.svg and relocate to app/images/ cp-13.40.0 (#44391)
bcb2b82445 release: changelog
73c875a3f6 refactor(analytics): migrate multichain chrome events (#43900)
84145c408f fix: mv3 sw lavamoat background wrapping (#44187)
3d173df60c fix(token-management): seed unified assets for non-EVM search imports cp-13.39.1 cp-13.40.0 (#44361)
a886918443 feat(ramps): add ramps controller hooks and selectors (#43963)
942441b93f fix: Fix Firefox detatched-window memory leak by avoiding DocumentPictureInPicture instantiation in Snow hook cp-13.39.2 (#44352)
a7485c7561 feat: support Robinhood chain on swaps cp-13.39.1 (#44347)
22c457ff91 chore: update CODEOWNERS for engagement team (#44336)
4e65bd74c9 chore: bump @metamask/profile-sync-controller to ^28.3.0 (#44344)
838c70370b fix(rewards): retry silent auth when remote flags hydrate after onboarding (#44282)
c93e5a143c refactor: migrate musd convert toast (#44206)
09d105c0bd feat: add Robinhood Infura RPC + assets ctrl bump cp-13.39.1 (#44331)
c1860fc58d fix(release): pin firefox bundle.sh per release tag (INFRA-3753) (#44121)
f0d9f25e2e refactor: consolidate Home page into single hook-based component (#44293)
b1158f292b feat(ramps): wire RampsController into background (#43962)
d3fe41296a fix: copy fixes for musd convert and perps cp-13.40.0 (#44332)
deaf6f0e86 chore: migrate captureTestError to LegacyBackgroundApiService (#44350)
9b3401b39e chore: onboarding Terms of Usage and Privacy Link e2e (#44323)
850b14df49 chore: migrate decodeTransactionData to LegacyBackgroundApiService (#44242)
f84631829d feat(notifications): include app version in push registration metadata (#43605)
f9c195294f chore: migrate isRelaySupported to LegacyBackgroundApiService (#44238)
b2b0f6b947 feat(hardware-wallets): add signing page copy and utilities (#43942)
9eeae6c1e0 feat(e2e): add Tron local node bootstrap (#44151)
4dac656a96 fix(confirmations): align warning icon inline with label in estimated changes section (#44207)
29435c41e6 feat(ci): verify release attestation before CWS upload (INFRA-3661) (#44123)
0eb7b6df11 feat(ci): attest webpack release zips at publish (INFRA-2665) (#44122)
521383313d refactor: address wallet-init review nits (#44116)
6d8b527c93 feat: extract Stellar asset activation UI component (#44193)
864daacd24 feat: show QR code for trending/explore deeplink instead of routing home (#44170)
2944262403 chore: add tooltips to order labels (#44290)
7ec2719d8b chore: resolve toast implementation (#44292)
0f840878ff release: Bump main version to 13.41.0 (#44328)
823e0a0eb9 Merge pull request #44325 from MetaMask/stable-main-13.39.0
f9bad587cc Merge origin/main into stable-main-13.39.0
0b5a203bd9 chore: deprecate old toast component (#44275)
9d4d19b5c5 feat: scrollable tab (#44316)
ad6f7bb54f feat(perps): gate full asset names behind perpsShowFullAssetNames flag cp-13.39.0 (#44304)
970a0c6a75 chore: migrate checkDelegationDisabled to LegacyBackgroundApiService (#44266)
ea6632be11 feat(networks): add Robinhood Chain as featured network (#44310)
3d8272de95 chore: update CODEOWNERS for money-movement team (#44314)
2b74a1ae0a refactor(analytics): migrate home activity and wallet overview events (#43899)
ed6e1a4a68 feat: added warning banner (#44309)
ba6e32f5b4 feat(engagement): Port deeplink bypass by route feature from mobile to extension (#43639)
b77923c40d chore: update transaction id copied translation (#44313)
b8921b2220 feat: upgrade notifications service controller to support v4 api (#44263)
db9e57370c feat: bump Tron snap 1.29.1 (#44306)
ea2c5e6415 perf(6915): memoize getApprovalFlows Selector (#44224)
7c2231cb17 feat: show complete onboarding screen only once (#44232)
ad91394089 refactor(analytics): migrate confirmations events (#43892)
5d65e7a8dc refactor(analytics): migrate swaps and bridge events (#43891)
11fb25664e chore: migrate isSendBundleSupported to LegacyBackgroundApiService (#44240)
104ef3781d test(e2e): add BTC activity cluster spec (#43005)
7a647f51f8 feat(hardware-wallets): add signing page components (#43941)
13663f6db8 refactor: add TransactionController to wallet initialization (#43182)
7820bf530c chore: migrate getPhishingResult to LegacyBackgroundApiService (#44255)
c15b8dbeee refactor(analytics): migrate perps events (#43890)
4d33ee059f chore: migrate throwTestError to LegacyBackgroundApiService (#44239)
94614aba0f chore: migrate getAssets to LegacyBackgroundApiService (#44241)
4a9c03cbeb fix(perps): hide perps balance and position data when privacy mode is enabled (#44262)
93e14da37f fix: updated added to chainlist icon and padding (#44268)
480d4f821e fix: arc swap assets picker missing prices (#44073)
5825f03d69 feat(perps): gate terminal backend behind perpsTerminalBackendEnabled feature flag cp-13.39.0 (#43989)
03230d6229 test: fix flaky test MetaMask onboarding User can add custom network during onboarding (#44243)
5652b6cb1e feat(stellar): add trustline support in transaction history v3 (#44200)
d5ccb0e794 chore(e2e): scaffold bitcoin-regtest-up bootstrap for BTC E2E (#42943)
2ea4542077 fix: transaction id row (#44188)
aa5378721b fix: swap tx fails when smart account upgrade is required cp-13.39.0 (#44291)
a85e8a0380 chore: remove unused selectors (#44278)
de7420417a Merge pull request #44272 from MetaMask/stable-main-13.38.1
7c3e420839 chore(component-library): remove unused legacy icon SVGs (#44227)
698a384cbb fix(ramps): remove network gating from buy entry points (#44069)
7f534c5cda chore: New Crowdin Translations by GitHub Action cp-13.39.0 (#43689)
e07fedcb92 Merge origin/main into stable-main-13.38.1
33acc092d8 chore: upgrade design system packages (v52.0.0) (#44226)
83378bca32 perf(6556): remove redundant isEqual from awaiting-signatures useSelector calls (#44234)
4d12b0cc00 feat: added transition for settings page (#44074)
65c0fca156 fix(perps): truncate long asset names in market list to a single line cp-13.39.0 (#44214)
04afd3c489 perf: replace deep equality with shallow + add result equality to filter-based transaction selectors (#44110)
ecaa92746c perf(6916): refactor core UX selectors to remove deep-equality subscriptions (#44235)
0be73a9e7a fix(onboarding): updated min-height for login-option cp-13.39.0 (#44265)
9ef5547abe bump: upgrade @metamask/assets-controller to ^10.1.0 (#44246)
38571fa64d refactor(analytics): move event enrichment downstream (#44219)
da8373fef1 feat: use canonical_profile_id as a segment trait instead of profile_id (#44213)
af45d23d92 refactor(analytics): migrate multichain accounts events (#43896)
523715f346 feat(musd): tag prefilled_max input type on Transaction Added event (#44211)
0eab632cb3 chore: bind updateHiddenAccountsList directly to AccountOrderController:updateHiddenAccountsList (#44245)
3fb4d44298 chore: bind updateAccountsList directly to AccountOrderController:updateAccountsList (#44244)
0c644a4a55 chore: remove unused endTrace from getApi (#44237)
89add44149 chore: migrate toggleExternalServices to LegacyBackgroundApiService (#44143)
d4ce5e48ab chore(assets): add robinhood svg (#44191)
787b18b802 feat: Bump Snaps packages (#44210)
4253ff3e2e chore(6928): Replace react-beautiful-dnd with @hello-pangea/dnd (#43328)
8f9719a7d9 refactor(analytics): migrate smart transactions controller events (#43902)
2f843003ed feat(e2e): add Tron seeder asset helpers (#44150)
a93e640377 chore: removed old token import modal (#43712)
3d60c993a6 test: enhance clikElementSafe (#44236)
c4933e235a refactor(analytics): migrate multichain account chrome events (#43919)
fbd638ea2c refactor(analytics): migrate accounts hardware wallet events (#43895)
da0bbb6375 fix: disable CTA swap button for Tron when no network fees retrieved (#44107)
6639fdb7c8 fix: bignumber issues everywhere cp-13.38.1 (#44216)
ee138ca34d feat: scam questionnaire on malicious internal send flows (#43822)
c1bbdd9676 refactor(analytics): migrate token management assets events (#43912)
44008b9886 feat(e2e): add java-tron local node configuration (#44149)
a5ebebb3b0 feat: replace use metametrics with useAnalytics hook for networks page (#44212)
e53335e0c7 chore: set bottom nav bar conditional rendering (#44215)
82846bc6a1 feat: added BFT consolidation feature for new users (#43935)
8f31233a4f refactor(analytics): migrate assets events (#43889)
6dc7a8dad8 chore: bind alignMultichainWallets directly to MultichainAccountService:alignWallets (#44134)
09a4ab422b refactor(hardware-wallets): unify signing tracker (#43940)
1a2ca55143 chore: remove unused trackInsightSnapView from getApi (#44135)
d063aa9af5 chore: bump assets controller to v10.0.0 ASSETS-3385 (#44055)
f4819cfd9c chore: bump @metamask/bitcoin-wallet-snap to ^1.14.2, @metamask/solana-wallet-snap to ^2.10.0 (#44209)
fdd45f6033 refactor(analytics): migrate network and navigation chrome events (#43918)
c9b563c309 refactor(analytics): migrate modals and name display events (#43917)
3b6129124e refactor(analytics): migrate unlock and rewards events (#43916)
09da33f257 feat(e2e): add shared local node fixture plumbing (#44148)
ff56170604 test: Sync Feature Flag Registry - 2026-07-07 01:33 UTC (#44204)
cf8762c11f feat: sync wallets/accounts via MWP QR (#43711)
f23dee8a95 feat: Add UI components for Ledger status screens (#43720)
efd4b3f69d chore: clean up legacy Tag storybook (#44186)
1f603c3ba2 fix(confirmations): show Pay with row on initial MM Pay page (#44190)
481a27f030 feat(stellar): add Stellar chain utilities (#44192)
fa3a49e3f7 ci: make check-template-and-add-labels.mts run in Node 24 (#44056)
767bc86afe fix(swaps): fix stale search results after network filter change cp-13.39.0 (#44194)
0cd68d537a ci: fix "All jobs pass" in cross-repo PRs (#44182)
34e80bb6d1 feat: create bottom bar UI (#44197)
5125b602a9 perf(6645): refactor feature-specific selectors in home.component (#43577)
ba8bb54199 test: update wallet-fixture-export.spec.ts to the latest state and prevent drift with wallet-fixture-validation.spec.ts (#44127)
6aab821565 refactor(analytics): migrate keychain and SRP events (#43897)
5e03105fad test(e2e): add BTC assets cluster spec (#43006)
4821f0d027 refactor(analytics): migrate platform library background events (#43920)
d1ce52bc0f refactor(analytics): migrate core platform background events (#43901)
d7b3a92f70 test(e2e): cover completing a BTC to USDC (ERC20) swap (#43834)
3924472a09 fix: prevent Sentry storage read recursion (#44057)
5f73f93b46 Merge pull request #44172 from MetaMask/stable-main-13.38.0
1eb7182a53 Merge origin/main into stable-main-13.38.0
dd7c20db7e fix: disable gas sponsorship for hw wallets cp 13.39.0 (#44144)
f68939ba26 chore: bind updateNetworksList directly to NetworkOrderController:updateNetworksList (#44133)
21b8d0c67d chore: bind handleSnapRequest directly to SnapController:handleRequest (#44132)
37ddaa468a perf: memoize getUnconnectedAccounts selector (#44109)
75730ef0cd test: fix flaky test Ledger Hardware unlocks multiple accounts at once and removes one (#44094)
e5ee1c4b21 chore: setup codeownership of metamask-controller (#44131)
a4d0a59d15 chore: use delay on the global spinner (#44120)
cd82cd4c09 test: fix update-fixtures due to github policy change on actions cache (#44128)
72a4b94be4 refactor(analytics): migrate backup and sync account events (#43915)
535522dab6 chore: move aus e2e mocks out of auth CO scope (#44106)
a2014674f6 refactor(analytics): migrate shield and subscription events (#43893)
69c2aa4135 refactor(analytics): migrate onboarding welcome events (#43914)
a01132e83a refactor(analytics): migrate onboarding flow events (#43894)
63e37788f6 feat: source AddressBookController from @metamask/wallet@6.0.0 (#44112)
09dc5d616e refactor: remove deprecated "turn on notifications" modal (#44098)
3215860c6e chore: bind createNextMultichainAccountGroup directly to MultichainAccountService:createNextMultichainAccountGroup (#44103)
90f149a51a feat(swaps): integrate bridge QuoteStatusManager behind feature flag cp-13.39.0 (#44006)
a1c57e10d3 feat: update rbtc rootstock native icon (#44115)
c150be98df feat: add React Refresh to webpack watch builds (#43703)
184edd940c test: add automated RC build workflow for Extension, aligned with Mobile's workflow, aligns Extension RC notifications with Mobile (#42960)
d98ee34687 chore: upgrade design system packages (v50.0.0) (#44090)
3413101307 release: Bump main version to 13.40.0 (#44119)
8023b3c7f2 fix: bignumber incident 1752 cp-13.38.0 (#44097)
1c43659138 refactor(analytics): migrate send flow confirmation metrics (#43913)
8951ee1d47 refactor(analytics): migrate settings and privacy events (#43898)
b374c83130 refactor(analytics): migrate earn/mUSD events (#43888)
58c79c4cba test: fix update-fixtures script permissions (#44111)

Changelog (8 commits from main at RC cut)
Commit Description
27ee2a2b77 Merge pull request #44395 from MetaMask/release/13.39.2
311d329644 Merge branch 'stable' into release/13.39.2
19c20c50b9 Merge pull request #44342 from MetaMask/release/13.39.1
52e9d05e7c release: release-changelog/13.39.2 (#44394)
383e8dfbe9 fix: mv3 sw lavamoat background wrapping (#44187) (#44402)
c7383581ac release(runway): cherry-pick fix: Fix Firefox detatched-window memory leak by avoiding DocumentPictureInPicture instantiation in Snow hook cp-13.39.2 (#44401)
dab19fc117 bump semvar version to 13.39.2
05052d192c Merge pull request #44117 from MetaMask/release/13.39.0

AI Test Plan

Risk Score High Risk Medium Risk Files Changed Commits
57/100 6 8 1313 188
Cherry-Pick Scenarios (4)

High Risk Scenarios (2)

1. Token Management – Non‑EVM Token Search/Import (Snaps)

Risk Level: HIGH

Why This Matters: Cherry-pick #44361 fixes seeding unified assets for non‑EVM search imports; without it, users can’t discover/import tokens on Snap-based networks, breaking basic asset management.

Test Steps:

  1. Install and enable a non‑EVM Snap that supports token lists (e.g., Tron Wallet Snap) and create a corresponding account.
  2. Open the account’s Assets view and use Import/Search to find a well‑known token (e.g., USDT on that network).
  3. Import the token and verify it appears in the list with correct symbol/decimals and a 0 or expected balance.
  4. Restart the extension and confirm the imported token persists and actions (send/view details) work within that Snap’s account.

2. Activity – Duplicate Pending Transaction Rows

Risk Level: HIGH

Why This Matters: Cherry-pick #44370 fixes extra pending rows from local state; duplicates confuse users, obscure the real status, and can cause mistaken actions.

Test Steps:

  1. On Ethereum, initiate a send and leave it pending; open Activity and verify only one pending row appears.
  2. Submit a second pending tx; confirm exactly two pending rows appear (no extras).
  3. Speed up or cancel one pending tx and confirm the list updates to remove or update the correct row.
  4. Lock and unlock the wallet; verify no extra pending rows reappear.

Medium Risk Scenarios (2)

1. Networks – Add and Use Featured Robinhood Chain

Risk Level: MEDIUM

Why This Matters: Cherry-pick #44346 adds a new featured network; incorrect metadata or switching issues can lead to failed transactions or mispriced balances.

Test Steps:

  1. Open Networks > Add a network and locate Robinhood Chain under Featured.
  2. Add the network; verify name/icon load, RPC and chain ID populate, and switch succeeds.
  3. Open a token detail or explorer link from this network and confirm URLs and native currency symbol display correctly.
  4. Switch back to Mainnet and return; ensure the custom network persists and is selectable.

2. Portfolio – Aggregated Balance Stability (Tracer change)

Risk Level: MEDIUM

Why This Matters: Cherry-pick #44460 removes a trace parameter in balance aggregation; while aimed at telemetry, it touches hot paths that could alter performance or accuracy.

Test Steps:

  1. With multiple accounts and histories, open Home and quickly switch between accounts 5–10 times.
  2. Observe that top-line balance updates smoothly without prolonged spinners or errors.
  3. Compare the top-line with a spot-check of asset values to ensure accuracy wasn’t affected.
  4. Leave the extension idle for 2–3 minutes and confirm no sudden spikes or recalculation loops occur.

Release Scenarios (10)

High Risk Scenarios (4)

1. State Migration (Migration 216) – Upgrade Safety

Risk Level: HIGH

Why This Matters: New migration (216) can corrupt or drop user data if it mishandles persisted state; validating upgrade integrity prevents data loss and broken sessions.

Test Steps:

  1. Start on 13.39.x with: at least 2 accounts (one imported), custom RPC network, several imported tokens/NFTs, and at least one connected dapp.
  2. Upgrade to 13.40.0 and unlock the wallet.
  3. Verify all accounts, balances, address book entries, tokens/NFTs, connected sites, and custom networks are intact.
  4. Perform a send on the custom network and confirm history displays correctly post-upgrade.

2. Seedless Onboarding – Migration and Resume

Risk Level: HIGH

Why This Matters: Seedless onboarding migrations changed; mid-flow users are susceptible to dead-ends or corrupted onboarding state after upgrade.

Test Steps:

  1. On 13.39.x, start seedless onboarding and stop mid-flow (e.g., after initial terms but before account creation).
  2. Upgrade to 13.40.0 and reopen the extension.
  3. Confirm you’re returned to the correct step with prior choices preserved, and you can complete onboarding without errors.
  4. After completion, verify the resulting account appears in the account list, settings reflect the chosen method, and dapp connections work.

3. Token Management – Asset List Control Bar and Sorting

Risk Level: HIGH

Why This Matters: Large refactor to asset list/control bar/sort components risks broken sorting, persistence, and search behavior that directly affects discoverability of assets.

Test Steps:

  1. With an account holding 8+ tokens of varying values, open the Assets tab.
  2. Use the control bar to sort by Value, Balance, and A–Z; confirm ordering updates correctly each time.
  3. Use search to filter by token symbol/name; clear the search and verify the full list returns with prior sort retained.
  4. Close and reopen the extension; confirm the previously selected sort persists.

4. Portfolio – Aggregated Balance Accuracy and Performance

Risk Level: HIGH

Why This Matters: Changes around balance aggregation can cause misreported totals or performance regressions that erode trust in displayed balances.

Test Steps:

  1. Use a profile with multiple accounts and networks; open the Home screen and note the total portfolio value.
  2. Manually sum prominent token values from Assets across accounts to spot-check the total.
  3. Rapidly switch between accounts and networks; observe for freezes/spinners and verify the total remains accurate.
  4. Leave the extension open for 2–3 minutes and confirm the total updates without spikes or stale values.

Medium Risk Scenarios (6)

1. Token Management – Inactive Asset Badge

Risk Level: MEDIUM

Why This Matters: New badge introduces compliance/safety cues; incorrect labeling or missing action-guards can lead users to interact with deprecated or unsafe assets.

Test Steps:

  1. In the token search/import UI, look for any token marked as Inactive (badge) and add/view it.
  2. Open the token details and verify the Inactive badge is visible and messaging is clear.
  3. Attempt actions like Swap/Bridge/Buy for the inactive token and confirm the UI either blocks or clearly warns.
  4. Remove the token and re-add it; confirm the badge state is consistent.

2. DeFi – Empty State and Protocol Cell Display

Risk Level: MEDIUM

Why This Matters: UI updates in DeFi cells/empty state can break discoverability and clarity of DeFi holdings, leading to confusion about portfolio composition.

Test Steps:

  1. On an account with no DeFi positions, open the DeFi section and confirm the empty state message appears with correct CTA (e.g., Learn or Discover).
  2. On an account with at least one DeFi position (if available), verify the protocol row shows name, network, and value.
  3. Click a DeFi protocol row and confirm navigation to details works without errors.
  4. Switch networks and ensure DeFi rows/empty state update appropriately.

3. Assets/Activity Views – List Virtualization and Counts

Risk Level: MEDIUM

Why This Matters: List component changes can introduce virtualization and state bugs (missing items, duplicates) that degrade trust and usability.

Test Steps:

  1. With 20+ assets and a long activity history, scroll to the end of both Assets and Activity lists.
  2. Verify no items disappear or duplicate when scrolling up/down quickly.
  3. Confirm counts (e.g., number of assets) remain stable after adding/removing a token.
  4. Switch accounts and return; verify the lists render correctly without stale or mixed content across accounts.

4. Analytics/MetaMetrics – Consent and Settings

Risk Level: MEDIUM

Why This Matters: Large analytics controller changes risk breaking privacy toggles or introducing UX regressions in consent handling.

Test Steps:

  1. Fresh install: opt out of MetaMetrics during onboarding; confirm Settings > Security & privacy shows MetaMetrics disabled.
  2. Toggle MetaMetrics ON in settings; navigate through various screens (Home, Activity, Send) and confirm no prompts or errors.
  3. Toggle OFF again; restart the extension and ensure the choice persists.
  4. Confirm no UI regressions or blocked flows when toggling.

5. Network Switching – Asset List and Balance Refresh

Risk Level: MEDIUM

Why This Matters: Asset list and sorting changes must remain correct across network boundaries to avoid misattribution of balances and tokens.

Test Steps:

  1. On Ethereum Mainnet, note the Assets order and values.
  2. Switch to a custom RPC network with different balances; confirm the Assets list refreshes correctly and previous network’s order/values do not bleed over.
  3. Switch back to Mainnet; verify the prior sort selection persists and values are correct.
  4. Use search on each network to confirm results are scoped properly.

6. Onboarding – Create vs Import Flow Reliability

Risk Level: MEDIUM

Why This Matters: Changes around onboarding action types and analytics must not interfere with the critical create/import paths.

Test Steps:

  1. Fresh install and complete Create Wallet flow; ensure you land on Home with a new account and settings initialized.
  2. Reset extension; complete Import Wallet with a known seed phrase; confirm correct account address is restored.
  3. In both cases, visit Settings and Accounts views to verify expected defaults (currency, network, metrics setting) are present.
  4. Connect to a site and approve; verify connection state functions as expected post-onboarding.

Teams Sign-off Status

Signed off: None yet

Awaiting sign-off (6):
Assets, Networks, Onboarding, Settings, Snaps, Transactions


Generated by AI Test Plan Analyzer (gpt-5) at 2026-07-15T16:49:57.082Z

AI generated test plan (JSON): test-plan-13.40.0.json

@metamask-ci

metamask-ci Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor
Builds ready [22224a2]
Deprecated Browserify fallback builds
⚡ Performance Benchmarks (Total: 🟢 19 pass · 🟡 2 warn · 🔴 3 fail)

Baseline (latest main): 9efc6d6 | Date: 7/16/2026 | Pipeline: 29475718780 | Baseline logs

Metricschrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 srpButtonToSrpForm(p95) [CI log]🔴 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🔴 [CI log]

Regressions (🔴 3 failures)

Interaction Benchmarks · Samples: 5
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
🔴 load_new_account
confirmTx
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
🟡 bridge_search_token

📈 Results compared to the previous 5 runs on main

  • ↓ loadNewAccount/load_new_account: -21%
  • ↓ loadNewAccount/total: -21%
  • ↑ confirmTx/confirm_tx: +46%
  • ↑ confirmTx/tbt: +12%
  • ↑ confirmTx/total: +46%
  • ↓ confirmTx/inp: -12%
  • ↓ bridgeUserActions/bridge_load_page: -30%
  • ↑ bridgeUserActions/longTaskCount: +25%
  • ↓ bridgeUserActions/tbt: -42%
  • ↓ bridgeUserActions/inp: -24%
  • ↑ bridgeUserActions/lcp: +13%
  • ↑ loadNewAccount/load_new_account: +592%
  • ↑ loadNewAccount/total: +592%
  • ↑ loadNewAccount/inp: +233%
  • ↓ loadNewAccount/fcp: -56%
  • ↑ loadNewAccount/lcp: +1141%
  • ↑ confirmTx/confirm_tx: +61%
  • ↓ confirmTx/longTaskCount: -100%
  • ↓ confirmTx/longTaskTotalDuration: -100%
  • ↓ confirmTx/longTaskMaxDuration: -100%
  • ↓ confirmTx/tbt: -100%
  • ↑ confirmTx/total: +61%
  • ↓ confirmTx/inp: -12%
  • ↓ confirmTx/fcp: -44%
  • ↑ confirmTx/lcp: +1148%
  • ↑ bridgeUserActions/bridge_load_page: +103%
  • ↑ bridgeUserActions/bridge_load_asset_picker: +99%
  • ↑ bridgeUserActions/bridge_search_token: +208%
  • ↓ bridgeUserActions/longTaskCount: -100%
  • ↓ bridgeUserActions/longTaskTotalDuration: -100%
  • ↓ bridgeUserActions/longTaskMaxDuration: -100%
  • ↓ bridgeUserActions/tbt: -100%
  • ↑ bridgeUserActions/total: +180%
  • ↓ bridgeUserActions/inp: -24%
  • ↓ bridgeUserActions/fcp: -55%
  • ↑ bridgeUserActions/lcp: +1163%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 loadNewAccount/INP: p75 288ms
Startup Benchmarks · Samples: 100
Benchmarkchrome-webpackfirefox-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
startupPowerUserHome
[Sentry log · main/release]
–🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • ↑ startupStandardHome/firstReactRender: +30%
  • ↑ startupStandardHome/numNetworkReqs: +13%
  • ↓ startupStandardHome/cls: -100%
  • ↑ startupStandardHome/uiStartup: +14%
  • ↑ startupStandardHome/load: +14%
  • ↑ startupStandardHome/domContentLoaded: +14%
  • ↓ startupStandardHome/domInteractive: -23%
  • ↑ startupStandardHome/backgroundConnect: +12%
  • ↑ startupStandardHome/firstReactRender: +33%
  • ↑ startupStandardHome/initialActions: +25%
  • ↑ startupStandardHome/loadScripts: +14%
  • ↑ startupStandardHome/setupStore: +20%
  • ↓ startupStandardHome/fcp: -20%
  • ↑ startupStandardHome/lcp: +12%
  • ↓ startupPowerUserHome/uiStartup: -45%
  • ↓ startupPowerUserHome/load: -42%
  • ↓ startupPowerUserHome/domContentLoaded: -41%
  • ↓ startupPowerUserHome/domInteractive: -32%
  • ↓ startupPowerUserHome/backgroundConnect: -51%
  • ↓ startupPowerUserHome/firstReactRender: -25%
  • ↓ startupPowerUserHome/initialActions: -50%
  • ↓ startupPowerUserHome/loadScripts: -42%
  • ↓ startupPowerUserHome/setupStore: -96%
  • ↓ startupPowerUserHome/inp: -43%
  • ↓ startupPowerUserHome/fcp: -30%
  • ↓ startupPowerUserHome/lcp: -46%
User Journey Benchmarks · Samples: 5 · real API 🔴 3
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 [CI log]
🔴 doneButtonToHomeScreen
🔴 total
🔴 [CI log]
🔴 total
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🔴 [CI log]
🔴 total
assetDetails
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
importSrpHome
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]
sendTransactions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
swap
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • ↑ onboardingImportWallet/srpButtonToSrpForm: +12%
  • ↓ onboardingImportWallet/metricsToWalletReadyScreen: -11%
  • ↑ onboardingImportWallet/doneButtonToHomeScreen: +51%
  • ↑ onboardingImportWallet/openAccountMenuToAccountListLoaded: +98%
  • ↑ onboardingImportWallet/longTaskCount: +18%
  • ↑ onboardingImportWallet/longTaskTotalDuration: +11%
  • ↑ onboardingImportWallet/total: +40%
  • ↑ onboardingNewWallet/srpButtonToPwForm: +17%
  • ↑ onboardingNewWallet/createPwToRecoveryScreen: +36%
  • ↑ onboardingNewWallet/skipBackupToMetricsScreen: +17%
  • ↑ onboardingNewWallet/agreeButtonToOnboardingSuccess: +15%
  • ↑ onboardingNewWallet/doneButtonToAssetList: +32%
  • ↑ onboardingNewWallet/longTaskCount: +43%
  • ↑ onboardingNewWallet/longTaskTotalDuration: +62%
  • ↑ onboardingNewWallet/longTaskMaxDuration: +20%
  • ↑ onboardingNewWallet/tbt: +121%
  • ↑ onboardingNewWallet/total: +30%
  • ↑ solanaAssetDetails/assetClickToPriceChart: +23%
  • ↓ solanaAssetDetails/longTaskCount: -100%
  • ↓ solanaAssetDetails/longTaskTotalDuration: -100%
  • ↓ solanaAssetDetails/longTaskMaxDuration: -100%
  • ↓ solanaAssetDetails/tbt: -100%
  • ↑ solanaAssetDetails/total: +23%
  • ↑ importSrpHome/openAccountMenuAfterLogin: +94%
  • ↓ importSrpHome/homeAfterImportWithNewWallet: -16%
  • ↑ importSrpHome/longTaskMaxDuration: +23%
  • ↑ importSrpHome/tbt: +14%
  • ↓ importSrpHome/total: -13%
  • ↓ importSrpHome/cls: -48%
  • ↓ sendTransactions/openSendPageFromHome: -18%
  • ↑ sendTransactions/selectTokenToSendFormLoaded: +22%
  • ↑ sendTransactions/reviewTransactionToConfirmationPage: +134%
  • ↑ sendTransactions/longTaskCount: +100%
  • ↑ sendTransactions/longTaskTotalDuration: +80%
  • ↑ sendTransactions/longTaskMaxDuration: +80%
  • ↓ sendTransactions/tbt: -100%
  • ↑ sendTransactions/total: +130%
  • ↓ swap/openSwapPageFromHome: -73%
  • ↓ swap/fetchAndDisplaySwapQuotes: -17%
  • ↓ swap/longTaskCount: -100%
  • ↓ swap/longTaskTotalDuration: -100%
  • ↓ swap/longTaskMaxDuration: -100%
  • ↓ swap/tbt: -100%
  • ↓ swap/total: -19%
  • ↓ swap/fcp: -11%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 importSrpHome/INP: p75 320ms
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]
Bundle sizes
  • background: 14.22 MiB
  • ui: 17.06 MiB
  • common: 0 Bytes
  • other: 998.07 KiB
  • contentScripts: 1.87 MiB
  • zip: 27.07 MiB
No matching bundle-size baseline was found in the history data, so diff values are omitted.

🍒 What's in this RC

Cherry-picks (173 commits)
Commit Description
22224a2ebd release(cp): bump: websocket-driver to fix audit
1ae883ad69 release(runway): cherry-pick chore: New Crowdin Translations by GitHub Action cp-13.40.0 (#44469)
143f29b8b4 release(runway): cherry-pick chore: reduce Sentry trace sampling cp-13.40.0 (#44462)
5d2bd7df70 release(runway): cherry-pick fix(sentry): Resolve AggregatedBalanceSelector transaction volume spike by not passing trace into getAggregatedBalanceForAccount cp-13.40.0 (#44460)
b040e51865 Merge branch 'stable' into release/13.40.0
8d99e9d5bb release(runway): cherry-pick chore: bump @metamask/tron-wallet-snap to ^1.31.0 cp-13.40.0 (#44428)
795203820e release: release-changelog/13.40.0 (#44327)
4dd7e83388 Merge branch 'stable' into release/13.40.0
55c0123941 release(runway): cherry-pick fix: extra pending row from local state cp-13.40.0 (#44370)
2c1234d055 release(runway): cherry-pick fix(assets): restore google.svg and relocate to app/images/ cp-13.40.0 (#44391)
bcb2b82445 release: changelog
73c875a3f6 refactor(analytics): migrate multichain chrome events (#43900)
84145c408f fix: mv3 sw lavamoat background wrapping (#44187)
3d173df60c fix(token-management): seed unified assets for non-EVM search imports cp-13.39.1 cp-13.40.0 (#44361)
a886918443 feat(ramps): add ramps controller hooks and selectors (#43963)
942441b93f fix: Fix Firefox detatched-window memory leak by avoiding DocumentPictureInPicture instantiation in Snow hook cp-13.39.2 (#44352)
a7485c7561 feat: support Robinhood chain on swaps cp-13.39.1 (#44347)
22c457ff91 chore: update CODEOWNERS for engagement team (#44336)
4e65bd74c9 chore: bump @metamask/profile-sync-controller to ^28.3.0 (#44344)
838c70370b fix(rewards): retry silent auth when remote flags hydrate after onboarding (#44282)
c93e5a143c refactor: migrate musd convert toast (#44206)
09d105c0bd feat: add Robinhood Infura RPC + assets ctrl bump cp-13.39.1 (#44331)
c1860fc58d fix(release): pin firefox bundle.sh per release tag (INFRA-3753) (#44121)
f0d9f25e2e refactor: consolidate Home page into single hook-based component (#44293)
b1158f292b feat(ramps): wire RampsController into background (#43962)
d3fe41296a fix: copy fixes for musd convert and perps cp-13.40.0 (#44332)
deaf6f0e86 chore: migrate captureTestError to LegacyBackgroundApiService (#44350)
9b3401b39e chore: onboarding Terms of Usage and Privacy Link e2e (#44323)
850b14df49 chore: migrate decodeTransactionData to LegacyBackgroundApiService (#44242)
f84631829d feat(notifications): include app version in push registration metadata (#43605)
f9c195294f chore: migrate isRelaySupported to LegacyBackgroundApiService (#44238)
b2b0f6b947 feat(hardware-wallets): add signing page copy and utilities (#43942)
9eeae6c1e0 feat(e2e): add Tron local node bootstrap (#44151)
4dac656a96 fix(confirmations): align warning icon inline with label in estimated changes section (#44207)
29435c41e6 feat(ci): verify release attestation before CWS upload (INFRA-3661) (#44123)
0eb7b6df11 feat(ci): attest webpack release zips at publish (INFRA-2665) (#44122)
521383313d refactor: address wallet-init review nits (#44116)
6d8b527c93 feat: extract Stellar asset activation UI component (#44193)
864daacd24 feat: show QR code for trending/explore deeplink instead of routing home (#44170)
2944262403 chore: add tooltips to order labels (#44290)
7ec2719d8b chore: resolve toast implementation (#44292)
0f840878ff release: Bump main version to 13.41.0 (#44328)
823e0a0eb9 Merge pull request #44325 from MetaMask/stable-main-13.39.0
f9bad587cc Merge origin/main into stable-main-13.39.0
0b5a203bd9 chore: deprecate old toast component (#44275)
9d4d19b5c5 feat: scrollable tab (#44316)
ad6f7bb54f feat(perps): gate full asset names behind perpsShowFullAssetNames flag cp-13.39.0 (#44304)
970a0c6a75 chore: migrate checkDelegationDisabled to LegacyBackgroundApiService (#44266)
ea6632be11 feat(networks): add Robinhood Chain as featured network (#44310)
3d8272de95 chore: update CODEOWNERS for money-movement team (#44314)
2b74a1ae0a refactor(analytics): migrate home activity and wallet overview events (#43899)
ed6e1a4a68 feat: added warning banner (#44309)
ba6e32f5b4 feat(engagement): Port deeplink bypass by route feature from mobile to extension (#43639)
b77923c40d chore: update transaction id copied translation (#44313)
b8921b2220 feat: upgrade notifications service controller to support v4 api (#44263)
db9e57370c feat: bump Tron snap 1.29.1 (#44306)
ea2c5e6415 perf(6915): memoize getApprovalFlows Selector (#44224)
7c2231cb17 feat: show complete onboarding screen only once (#44232)
ad91394089 refactor(analytics): migrate confirmations events (#43892)
5d65e7a8dc refactor(analytics): migrate swaps and bridge events (#43891)
11fb25664e chore: migrate isSendBundleSupported to LegacyBackgroundApiService (#44240)
104ef3781d test(e2e): add BTC activity cluster spec (#43005)
7a647f51f8 feat(hardware-wallets): add signing page components (#43941)
13663f6db8 refactor: add TransactionController to wallet initialization (#43182)
7820bf530c chore: migrate getPhishingResult to LegacyBackgroundApiService (#44255)
c15b8dbeee refactor(analytics): migrate perps events (#43890)
4d33ee059f chore: migrate throwTestError to LegacyBackgroundApiService (#44239)
94614aba0f chore: migrate getAssets to LegacyBackgroundApiService (#44241)
4a9c03cbeb fix(perps): hide perps balance and position data when privacy mode is enabled (#44262)
93e14da37f fix: updated added to chainlist icon and padding (#44268)
480d4f821e fix: arc swap assets picker missing prices (#44073)
5825f03d69 feat(perps): gate terminal backend behind perpsTerminalBackendEnabled feature flag cp-13.39.0 (#43989)
03230d6229 test: fix flaky test MetaMask onboarding User can add custom network during onboarding (#44243)
5652b6cb1e feat(stellar): add trustline support in transaction history v3 (#44200)
d5ccb0e794 chore(e2e): scaffold bitcoin-regtest-up bootstrap for BTC E2E (#42943)
2ea4542077 fix: transaction id row (#44188)
aa5378721b fix: swap tx fails when smart account upgrade is required cp-13.39.0 (#44291)
a85e8a0380 chore: remove unused selectors (#44278)
de7420417a Merge pull request #44272 from MetaMask/stable-main-13.38.1
7c3e420839 chore(component-library): remove unused legacy icon SVGs (#44227)
698a384cbb fix(ramps): remove network gating from buy entry points (#44069)
7f534c5cda chore: New Crowdin Translations by GitHub Action cp-13.39.0 (#43689)
e07fedcb92 Merge origin/main into stable-main-13.38.1
33acc092d8 chore: upgrade design system packages (v52.0.0) (#44226)
83378bca32 perf(6556): remove redundant isEqual from awaiting-signatures useSelector calls (#44234)
4d12b0cc00 feat: added transition for settings page (#44074)
65c0fca156 fix(perps): truncate long asset names in market list to a single line cp-13.39.0 (#44214)
04afd3c489 perf: replace deep equality with shallow + add result equality to filter-based transaction selectors (#44110)
ecaa92746c perf(6916): refactor core UX selectors to remove deep-equality subscriptions (#44235)
0be73a9e7a fix(onboarding): updated min-height for login-option cp-13.39.0 (#44265)
9ef5547abe bump: upgrade @metamask/assets-controller to ^10.1.0 (#44246)
38571fa64d refactor(analytics): move event enrichment downstream (#44219)
da8373fef1 feat: use canonical_profile_id as a segment trait instead of profile_id (#44213)
af45d23d92 refactor(analytics): migrate multichain accounts events (#43896)
523715f346 feat(musd): tag prefilled_max input type on Transaction Added event (#44211)
0eab632cb3 chore: bind updateHiddenAccountsList directly to AccountOrderController:updateHiddenAccountsList (#44245)
3fb4d44298 chore: bind updateAccountsList directly to AccountOrderController:updateAccountsList (#44244)
0c644a4a55 chore: remove unused endTrace from getApi (#44237)
89add44149 chore: migrate toggleExternalServices to LegacyBackgroundApiService (#44143)
d4ce5e48ab chore(assets): add robinhood svg (#44191)
787b18b802 feat: Bump Snaps packages (#44210)
4253ff3e2e chore(6928): Replace react-beautiful-dnd with @hello-pangea/dnd (#43328)
8f9719a7d9 refactor(analytics): migrate smart transactions controller events (#43902)
2f843003ed feat(e2e): add Tron seeder asset helpers (#44150)
a93e640377 chore: removed old token import modal (#43712)
3d60c993a6 test: enhance clikElementSafe (#44236)
c4933e235a refactor(analytics): migrate multichain account chrome events (#43919)
fbd638ea2c refactor(analytics): migrate accounts hardware wallet events (#43895)
da0bbb6375 fix: disable CTA swap button for Tron when no network fees retrieved (#44107)
6639fdb7c8 fix: bignumber issues everywhere cp-13.38.1 (#44216)
ee138ca34d feat: scam questionnaire on malicious internal send flows (#43822)
c1bbdd9676 refactor(analytics): migrate token management assets events (#43912)
44008b9886 feat(e2e): add java-tron local node configuration (#44149)
a5ebebb3b0 feat: replace use metametrics with useAnalytics hook for networks page (#44212)
e53335e0c7 chore: set bottom nav bar conditional rendering (#44215)
82846bc6a1 feat: added BFT consolidation feature for new users (#43935)
8f31233a4f refactor(analytics): migrate assets events (#43889)
6dc7a8dad8 chore: bind alignMultichainWallets directly to MultichainAccountService:alignWallets (#44134)
09a4ab422b refactor(hardware-wallets): unify signing tracker (#43940)
1a2ca55143 chore: remove unused trackInsightSnapView from getApi (#44135)
d063aa9af5 chore: bump assets controller to v10.0.0 ASSETS-3385 (#44055)
f4819cfd9c chore: bump @metamask/bitcoin-wallet-snap to ^1.14.2, @metamask/solana-wallet-snap to ^2.10.0 (#44209)
fdd45f6033 refactor(analytics): migrate network and navigation chrome events (#43918)
c9b563c309 refactor(analytics): migrate modals and name display events (#43917)
3b6129124e refactor(analytics): migrate unlock and rewards events (#43916)
09da33f257 feat(e2e): add shared local node fixture plumbing (#44148)
ff56170604 test: Sync Feature Flag Registry - 2026-07-07 01:33 UTC (#44204)
cf8762c11f feat: sync wallets/accounts via MWP QR (#43711)
f23dee8a95 feat: Add UI components for Ledger status screens (#43720)
efd4b3f69d chore: clean up legacy Tag storybook (#44186)
1f603c3ba2 fix(confirmations): show Pay with row on initial MM Pay page (#44190)
481a27f030 feat(stellar): add Stellar chain utilities (#44192)
fa3a49e3f7 ci: make check-template-and-add-labels.mts run in Node 24 (#44056)
767bc86afe fix(swaps): fix stale search results after network filter change cp-13.39.0 (#44194)
0cd68d537a ci: fix "All jobs pass" in cross-repo PRs (#44182)
34e80bb6d1 feat: create bottom bar UI (#44197)
5125b602a9 perf(6645): refactor feature-specific selectors in home.component (#43577)
ba8bb54199 test: update wallet-fixture-export.spec.ts to the latest state and prevent drift with wallet-fixture-validation.spec.ts (#44127)
6aab821565 refactor(analytics): migrate keychain and SRP events (#43897)
5e03105fad test(e2e): add BTC assets cluster spec (#43006)
4821f0d027 refactor(analytics): migrate platform library background events (#43920)
d1ce52bc0f refactor(analytics): migrate core platform background events (#43901)
d7b3a92f70 test(e2e): cover completing a BTC to USDC (ERC20) swap (#43834)
3924472a09 fix: prevent Sentry storage read recursion (#44057)
5f73f93b46 Merge pull request #44172 from MetaMask/stable-main-13.38.0
1eb7182a53 Merge origin/main into stable-main-13.38.0
dd7c20db7e fix: disable gas sponsorship for hw wallets cp 13.39.0 (#44144)
f68939ba26 chore: bind updateNetworksList directly to NetworkOrderController:updateNetworksList (#44133)
21b8d0c67d chore: bind handleSnapRequest directly to SnapController:handleRequest (#44132)
37ddaa468a perf: memoize getUnconnectedAccounts selector (#44109)
75730ef0cd test: fix flaky test Ledger Hardware unlocks multiple accounts at once and removes one (#44094)
e5ee1c4b21 chore: setup codeownership of metamask-controller (#44131)
a4d0a59d15 chore: use delay on the global spinner (#44120)
cd82cd4c09 test: fix update-fixtures due to github policy change on actions cache (#44128)
72a4b94be4 refactor(analytics): migrate backup and sync account events (#43915)
535522dab6 chore: move aus e2e mocks out of auth CO scope (#44106)
a2014674f6 refactor(analytics): migrate shield and subscription events (#43893)
69c2aa4135 refactor(analytics): migrate onboarding welcome events (#43914)
a01132e83a refactor(analytics): migrate onboarding flow events (#43894)
63e37788f6 feat: source AddressBookController from @metamask/wallet@6.0.0 (#44112)
09dc5d616e refactor: remove deprecated "turn on notifications" modal (#44098)
3215860c6e chore: bind createNextMultichainAccountGroup directly to MultichainAccountService:createNextMultichainAccountGroup (#44103)
90f149a51a feat(swaps): integrate bridge QuoteStatusManager behind feature flag cp-13.39.0 (#44006)
a1c57e10d3 feat: update rbtc rootstock native icon (#44115)
c150be98df feat: add React Refresh to webpack watch builds (#43703)
184edd940c test: add automated RC build workflow for Extension, aligned with Mobile's workflow, aligns Extension RC notifications with Mobile (#42960)
d98ee34687 chore: upgrade design system packages (v50.0.0) (#44090)
3413101307 release: Bump main version to 13.40.0 (#44119)
8023b3c7f2 fix: bignumber incident 1752 cp-13.38.0 (#44097)
1c43659138 refactor(analytics): migrate send flow confirmation metrics (#43913)
8951ee1d47 refactor(analytics): migrate settings and privacy events (#43898)
b374c83130 refactor(analytics): migrate earn/mUSD events (#43888)
58c79c4cba test: fix update-fixtures script permissions (#44111)

Changelog (8 commits from main at RC cut)
Commit Description
27ee2a2b77 Merge pull request #44395 from MetaMask/release/13.39.2
311d329644 Merge branch 'stable' into release/13.39.2
19c20c50b9 Merge pull request #44342 from MetaMask/release/13.39.1
52e9d05e7c release: release-changelog/13.39.2 (#44394)
383e8dfbe9 fix: mv3 sw lavamoat background wrapping (#44187) (#44402)
c7383581ac release(runway): cherry-pick fix: Fix Firefox detatched-window memory leak by avoiding DocumentPictureInPicture instantiation in Snow hook cp-13.39.2 (#44401)
dab19fc117 bump semvar version to 13.39.2
05052d192c Merge pull request #44117 from MetaMask/release/13.39.0

AI Test Plan

Risk Score High Risk Medium Risk Files Changed Commits
53/100 5 8 1313 189
Cherry-Pick Scenarios (4)

High Risk Scenarios (2)

1. Token Management — Unified assets seeding for non-EVM search/import

Risk Level: HIGH

Why This Matters: Cherry-pick 44361 fixes non-EVM asset seeding in search/import; mistakes here create cross-network asset confusion or duplicate entries.

Test Steps:

  1. Enable a non-EVM account (e.g., install/enable Tron Snap) and open the token import/search on that account.
  2. Search for a well-known non-EVM asset (e.g., USDT on Tron), import it, and verify correct symbol, logo, and decimals appear once (no duplicates).
  3. Switch to an EVM account and confirm the non-EVM asset does not leak into the EVM asset list/search results; switch back and verify persistence after reload.

2. Activity Feed — Remove extra pending row from local state

Risk Level: HIGH

Why This Matters: Cherry-pick 44370 fixes duplicate pending entries; duplicates degrade trust and make it hard to track real transaction states.

Test Steps:

  1. Start a transaction and keep it pending; reopen the extension and view Activity.
  2. Verify only one pending row is shown; speed up or cancel and ensure the same row updates status without leaving a duplicate.
  3. After confirmation, confirm only one confirmed row remains for the transaction.

Medium Risk Scenarios (2)

1. Network Management — Add Robinhood Chain as featured network

Risk Level: MEDIUM

Why This Matters: Cherry-pick 44346 adds a new featured network; incorrect chain metadata or switching can strand users on a broken network.

Test Steps:

  1. Open Add network > Featured and select 'Robinhood Chain'; review RPC, chain ID, symbol, and explorer links.
  2. Add and switch to Robinhood Chain; verify network indicator, currency symbol, and basic account view load without errors.
  3. Open network details in Settings and remove the network; confirm it is removed and you can switch back to Mainnet.

2. Portfolio Balance Selector — Remove tracing from balance aggregation

Risk Level: MEDIUM

Why This Matters: Cherry-pick 44460 alters the balance aggregation call path; unintended side-effects can impact accuracy or performance of portfolio totals.

Test Steps:

  1. With many tokens and multiple accounts, open Home and note the total balance; switch accounts rapidly 5–10 times.
  2. Confirm totals remain accurate and the UI stays responsive (no freezes or crashes) during rapid switches.
  3. Reload the extension and verify totals are consistent before and after reload.

Release Scenarios (9)

High Risk Scenarios (3)

1. State Migrations (Migration 216 + seedless onboarding migrations)

Risk Level: HIGH

Why This Matters: New migrations can reshape stored data; regressions may cause data loss, broken unlocks, or inconsistent activity/history after upgrade.

Test Steps:

  1. Install a previous stable version (e.g., 13.39.x), create a new wallet, add a second account, and set a password.
  2. Add a custom network, import a few tokens and one NFT, and initiate one pending transaction (leave it pending).
  3. Upgrade the same profile to 13.40.0, unlock, and wait for the home screen to fully load.
  4. Verify accounts, networks, tokens, NFTs, and activity entries are present (no loss/duplication); confirm security and privacy settings (e.g., MetaMetrics opt-in state) are preserved.
  5. Restart the extension and re-verify state persistence and integrity.

2. Analytics/MetaMetrics opt-in/out and event gating

Risk Level: HIGH

Why This Matters: Large refactors in analytics controllers/adapters can accidentally block flows, spam prompts, or ignore user consent.

Test Steps:

  1. Fresh install 13.40.0 and complete onboarding choosing 'No thanks' for MetaMetrics; confirm the setting shows disabled in Settings > Security & privacy.
  2. Navigate through Home, Assets, Activity, and Settings; perform a small test transaction and ensure no unexpected prompts/errors appear.
  3. Toggle MetaMetrics on in Settings and confirm consent flow; navigate and sign a message and a simple transaction.
  4. Lock and unlock; verify the preference persists and no UI regressions (e.g., stuck spinners or errors) occur.

3. Assets list sorting and filter control bar

Risk Level: HIGH

Why This Matters: Significant UI updates to asset list and sort controls risk incorrect ordering, broken filtering, or lost user preferences.

Test Steps:

  1. Ensure the wallet has 6+ tokens with varied balances; open the Assets tab.
  2. Use the Sort control to sort by Name (A→Z), then by Balance (high→low), then by Value (high→low); verify each ordering is correct.
  3. Use the search/filter input to narrow results and confirm sorting is still respected for the filtered set.
  4. Close and reopen the extension; verify the last selected sort is remembered and correctly applied.

Medium Risk Scenarios (6)

1. Asset Inactive Badge and token details

Risk Level: MEDIUM

Why This Matters: New UI component introduces risk of mislabeling tokens or blocking legitimate actions, impacting user trust and safety.

Test Steps:

  1. Import or detect a token flagged as inactive/delisted on a supported network (e.g., a deprecated token known in MetaMask’s registry).
  2. Verify the 'Inactive' badge appears on the token in the Assets list and on its details screen.
  3. Attempt to Send that token; ensure any warning copy displays correctly and that you can safely cancel and return.
  4. Remove and re-import the token; confirm the badge and warnings behave consistently.

2. DeFi list empty state and protocol cells

Risk Level: MEDIUM

Why This Matters: UI copy/structure changes in DeFi lists can cause rendering or formatting regressions that confuse users or hide opportunities.

Test Steps:

  1. On a wallet with no DeFi positions, open the DeFi tab and verify the updated empty state copy/CTA renders correctly.
  2. Connect to Mainnet and interact with a supported DeFi protocol via a dapp; return to the DeFi tab and verify protocol rows render with correct name, APY/APR formatting, and fiat values.
  3. Tap a protocol row; ensure it deep-links correctly and back navigation returns to the list with the same state.

3. Portfolio total vs per-asset balances consistency

Risk Level: MEDIUM

Why This Matters: Selector and controller changes around balances can produce incorrect or unstable totals, undermining portfolio accuracy.

Test Steps:

  1. With multiple tokens across networks, note the total fiat balance at the top of Home.
  2. Manually sum visible token fiat values and confirm the total matches (accounting for hidden/zero-asset settings).
  3. Switch accounts and networks rapidly; confirm totals update smoothly without temporary extreme values or stutters.
  4. Reload the extension and verify totals remain consistent.

4. Seedless onboarding state continuity

Risk Level: MEDIUM

Why This Matters: Changes in seedless onboarding migrations can break access or invalidate stored session/authorization data.

Test Steps:

  1. From a prior version with a seedless/passkey-created wallet, upgrade to 13.40.0 and unlock.
  2. Verify accounts and permissions are intact and you are not forced to re-onboard.
  3. Connect to a dapp and sign a test message/transaction; confirm signing flows are uninterrupted.
  4. Lock and unlock; ensure no unexpected migration prompts or errors appear.

5. Activity feed during pending→confirmed transitions

Risk Level: MEDIUM

Why This Matters: List and rendering updates can cause subtle duplication or stale rows during state transitions, confusing users reviewing history.

Test Steps:

  1. Send a transaction to create a pending entry and keep the Activity tab open.
  2. When the transaction confirms, verify exactly one row updates in place (status, timestamp, and details) without duplicates or disappearing items.
  3. Open the activity details and verify nonce, gas, and timestamps remain correct after the status change.

6. Network management sanity (switching and visibility)

Risk Level: MEDIUM

Why This Matters: Broad UI changes can unintentionally regress core network switching and visibility behaviors.

Test Steps:

  1. Switch between Ethereum Mainnet and at least two test networks; verify balances and token lists update accordingly.
  2. Open Add network flow, view a featured network’s details, then cancel; ensure the current network remains unchanged.
  3. Toggle 'Show test networks' in settings and confirm the network selector updates immediately.

Teams Sign-off Status

Signed off: None yet

Awaiting sign-off (3):
Assets, Networks, Onboarding


Generated by AI Test Plan Analyzer (gpt-5) at 2026-07-16T06:35:35.154Z

AI generated test plan (JSON): test-plan-13.40.0.json

@HowardBraham

Copy link
Copy Markdown
Contributor

@metamaskbot update-attributions

@metamaskbot

Copy link
Copy Markdown
Collaborator Author

Attributions update failed. You can review the logs or retry the attributions update here

@HowardBraham

Copy link
Copy Markdown
Contributor

@SocketSecurity ignore all

@HowardBraham

Copy link
Copy Markdown
Contributor

@metamaskbot update-attributions

@metamaskbot

Copy link
Copy Markdown
Collaborator Author

Attributions update failed. You can review the logs or retry the attributions update here

1 similar comment
@metamaskbot

Copy link
Copy Markdown
Collaborator Author

Attributions update failed. You can review the logs or retry the attributions update here

metamaskbot and others added 2 commits July 16, 2026 19:23
…nchDarkly flag cp-13.40.0 (#44582)

- feat: gate scam questionnaire behind LaunchDarkly flag cp-13.40.0 (#44496)

CHANGELOG entry: null
@metamask-ci

metamask-ci Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor
Builds ready [6d442d4]
Deprecated Browserify fallback builds
⚡ Performance Benchmarks (Total: 🟢 17 pass · 🟡 5 warn · 🔴 2 fail)

Baseline (latest main): 1456a21 | Date: 7/16/2026 | Pipeline: 29529502725 | Baseline logs

Metricschrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 doneButtonToHomeScreen(p95) [CI log]🔴 [CI log]

Regressions (🔴 2 failures)

Interaction Benchmarks · Samples: 5
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
confirmTx
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • ↓ loadNewAccount/inp: -15%
  • ↓ loadNewAccount/lcp: -13%
  • ↑ confirmTx/confirm_tx: +45%
  • ↑ confirmTx/total: +45%
  • ↑ bridgeUserActions/bridge_load_asset_picker: +27%
  • ↑ bridgeUserActions/longTaskCount: +25%
  • ↑ bridgeUserActions/longTaskTotalDuration: +22%
  • ↓ bridgeUserActions/longTaskMaxDuration: -17%
  • ↑ bridgeUserActions/tbt: +11%
  • ↑ bridgeUserActions/inp: +12%
  • ↓ bridgeUserActions/lcp: -18%
  • ↑ loadNewAccount/load_new_account: +37%
  • ↑ loadNewAccount/total: +37%
  • ↓ loadNewAccount/inp: -31%
  • ↓ loadNewAccount/fcp: -48%
  • ↑ loadNewAccount/lcp: +1128%
  • ↑ confirmTx/confirm_tx: +57%
  • ↓ confirmTx/longTaskCount: -100%
  • ↓ confirmTx/longTaskTotalDuration: -100%
  • ↓ confirmTx/longTaskMaxDuration: -100%
  • ↓ confirmTx/tbt: -100%
  • ↑ confirmTx/total: +57%
  • ↓ confirmTx/fcp: -46%
  • ↑ confirmTx/lcp: +1185%
  • ↑ bridgeUserActions/bridge_load_page: +191%
  • ↑ bridgeUserActions/bridge_load_asset_picker: +66%
  • ↓ bridgeUserActions/bridge_search_token: -10%
  • ↓ bridgeUserActions/longTaskCount: -100%
  • ↓ bridgeUserActions/longTaskTotalDuration: -100%
  • ↓ bridgeUserActions/longTaskMaxDuration: -100%
  • ↓ bridgeUserActions/tbt: -100%
  • ↑ bridgeUserActions/total: +21%
  • ↑ bridgeUserActions/lcp: +995%
Startup Benchmarks · Samples: 100
Benchmarkchrome-webpackfirefox-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
startupPowerUserHome
[Sentry log · main/release]
–🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • ↓ startupStandardHome/lcp: -33%
  • ↓ startupStandardHome/domInteractive: -13%
  • ↓ startupPowerUserHome/domInteractive: -14%
  • ↓ startupPowerUserHome/inp: -13%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 startupPowerUserHome/LCP: p75 3.3s
User Journey Benchmarks · Samples: 5 · real API 🔴 2
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 [CI log]
🔴 doneButtonToHomeScreen
🔴 total
🔴 [CI log]
🔴 total
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
🟡 total
assetDetails
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
importSrpHome
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]
sendTransactions
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]
swap
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • ↓ onboardingImportWallet/metricsToWalletReadyScreen: -15%
  • ↑ onboardingImportWallet/doneButtonToHomeScreen: +41%
  • ↓ onboardingImportWallet/openAccountMenuToAccountListLoaded: -79%
  • ↑ onboardingImportWallet/longTaskCount: +38%
  • ↑ onboardingImportWallet/longTaskTotalDuration: +29%
  • ↑ onboardingImportWallet/tbt: +18%
  • ↑ onboardingImportWallet/total: +36%
  • ↓ onboardingNewWallet/doneButtonToAssetList: -20%
  • ↓ onboardingNewWallet/longTaskCount: -12%
  • ↓ onboardingNewWallet/longTaskTotalDuration: -30%
  • ↓ onboardingNewWallet/longTaskMaxDuration: -39%
  • ↓ onboardingNewWallet/tbt: -42%
  • ↓ onboardingNewWallet/total: -18%
  • ↓ solanaAssetDetails/longTaskCount: -100%
  • ↓ solanaAssetDetails/longTaskTotalDuration: -100%
  • ↓ solanaAssetDetails/longTaskMaxDuration: -100%
  • ↓ solanaAssetDetails/tbt: -100%
  • ↑ solanaAssetDetails/inp: +30%
  • ↓ solanaAssetDetails/lcp: -10%
  • ↑ importSrpHome/loginToHomeScreen: +34%
  • ↓ importSrpHome/openAccountMenuAfterLogin: -18%
  • ↓ importSrpHome/homeAfterImportWithNewWallet: -46%
  • ↑ importSrpHome/longTaskTotalDuration: +22%
  • ↑ importSrpHome/longTaskMaxDuration: +28%
  • ↑ importSrpHome/tbt: +48%
  • ↓ importSrpHome/total: -40%
  • ↑ importSrpHome/cls: +100%
  • ↑ sendTransactions/openSendPageFromHome: +107%
  • ↑ sendTransactions/reviewTransactionToConfirmationPage: +13%
  • ↑ sendTransactions/total: +14%
  • ↓ sendTransactions/lcp: -12%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 importSrpHome/INP: p75 312ms
  • 🟡 sendTransactions/INP: p75 224ms
  • 🟡 sendTransactions/FCP: p75 1.8s
  • 🟡 swap/FCP: p75 2.0s
  • 🟡 swap/LCP: p75 2.5s
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]
Bundle sizes
  • background: 14.22 MiB
  • ui: 17.06 MiB
  • common: 0 Bytes
  • other: 998.07 KiB
  • contentScripts: 1.87 MiB
  • zip: 27.07 MiB
No matching bundle-size baseline was found in the history data, so diff values are omitted.

🍒 What's in this RC

Cherry-picks (175 commits)
Commit Description
6d442d4dac release(runway): cherry-pick feat: gate scam questionnaire behind LaunchDarkly flag cp-13.40.0 (#44582)
ea247cf927 release: update attributions
22224a2ebd release(cp): bump: websocket-driver to fix audit
1ae883ad69 release(runway): cherry-pick chore: New Crowdin Translations by GitHub Action cp-13.40.0 (#44469)
143f29b8b4 release(runway): cherry-pick chore: reduce Sentry trace sampling cp-13.40.0 (#44462)
5d2bd7df70 release(runway): cherry-pick fix(sentry): Resolve AggregatedBalanceSelector transaction volume spike by not passing trace into getAggregatedBalanceForAccount cp-13.40.0 (#44460)
b040e51865 Merge branch 'stable' into release/13.40.0
8d99e9d5bb release(runway): cherry-pick chore: bump @metamask/tron-wallet-snap to ^1.31.0 cp-13.40.0 (#44428)
795203820e release: release-changelog/13.40.0 (#44327)
4dd7e83388 Merge branch 'stable' into release/13.40.0
55c0123941 release(runway): cherry-pick fix: extra pending row from local state cp-13.40.0 (#44370)
2c1234d055 release(runway): cherry-pick fix(assets): restore google.svg and relocate to app/images/ cp-13.40.0 (#44391)
bcb2b82445 release: changelog
73c875a3f6 refactor(analytics): migrate multichain chrome events (#43900)
84145c408f fix: mv3 sw lavamoat background wrapping (#44187)
3d173df60c fix(token-management): seed unified assets for non-EVM search imports cp-13.39.1 cp-13.40.0 (#44361)
a886918443 feat(ramps): add ramps controller hooks and selectors (#43963)
942441b93f fix: Fix Firefox detatched-window memory leak by avoiding DocumentPictureInPicture instantiation in Snow hook cp-13.39.2 (#44352)
a7485c7561 feat: support Robinhood chain on swaps cp-13.39.1 (#44347)
22c457ff91 chore: update CODEOWNERS for engagement team (#44336)
4e65bd74c9 chore: bump @metamask/profile-sync-controller to ^28.3.0 (#44344)
838c70370b fix(rewards): retry silent auth when remote flags hydrate after onboarding (#44282)
c93e5a143c refactor: migrate musd convert toast (#44206)
09d105c0bd feat: add Robinhood Infura RPC + assets ctrl bump cp-13.39.1 (#44331)
c1860fc58d fix(release): pin firefox bundle.sh per release tag (INFRA-3753) (#44121)
f0d9f25e2e refactor: consolidate Home page into single hook-based component (#44293)
b1158f292b feat(ramps): wire RampsController into background (#43962)
d3fe41296a fix: copy fixes for musd convert and perps cp-13.40.0 (#44332)
deaf6f0e86 chore: migrate captureTestError to LegacyBackgroundApiService (#44350)
9b3401b39e chore: onboarding Terms of Usage and Privacy Link e2e (#44323)
850b14df49 chore: migrate decodeTransactionData to LegacyBackgroundApiService (#44242)
f84631829d feat(notifications): include app version in push registration metadata (#43605)
f9c195294f chore: migrate isRelaySupported to LegacyBackgroundApiService (#44238)
b2b0f6b947 feat(hardware-wallets): add signing page copy and utilities (#43942)
9eeae6c1e0 feat(e2e): add Tron local node bootstrap (#44151)
4dac656a96 fix(confirmations): align warning icon inline with label in estimated changes section (#44207)
29435c41e6 feat(ci): verify release attestation before CWS upload (INFRA-3661) (#44123)
0eb7b6df11 feat(ci): attest webpack release zips at publish (INFRA-2665) (#44122)
521383313d refactor: address wallet-init review nits (#44116)
6d8b527c93 feat: extract Stellar asset activation UI component (#44193)
864daacd24 feat: show QR code for trending/explore deeplink instead of routing home (#44170)
2944262403 chore: add tooltips to order labels (#44290)
7ec2719d8b chore: resolve toast implementation (#44292)
0f840878ff release: Bump main version to 13.41.0 (#44328)
823e0a0eb9 Merge pull request #44325 from MetaMask/stable-main-13.39.0
f9bad587cc Merge origin/main into stable-main-13.39.0
0b5a203bd9 chore: deprecate old toast component (#44275)
9d4d19b5c5 feat: scrollable tab (#44316)
ad6f7bb54f feat(perps): gate full asset names behind perpsShowFullAssetNames flag cp-13.39.0 (#44304)
970a0c6a75 chore: migrate checkDelegationDisabled to LegacyBackgroundApiService (#44266)
ea6632be11 feat(networks): add Robinhood Chain as featured network (#44310)
3d8272de95 chore: update CODEOWNERS for money-movement team (#44314)
2b74a1ae0a refactor(analytics): migrate home activity and wallet overview events (#43899)
ed6e1a4a68 feat: added warning banner (#44309)
ba6e32f5b4 feat(engagement): Port deeplink bypass by route feature from mobile to extension (#43639)
b77923c40d chore: update transaction id copied translation (#44313)
b8921b2220 feat: upgrade notifications service controller to support v4 api (#44263)
db9e57370c feat: bump Tron snap 1.29.1 (#44306)
ea2c5e6415 perf(6915): memoize getApprovalFlows Selector (#44224)
7c2231cb17 feat: show complete onboarding screen only once (#44232)
ad91394089 refactor(analytics): migrate confirmations events (#43892)
5d65e7a8dc refactor(analytics): migrate swaps and bridge events (#43891)
11fb25664e chore: migrate isSendBundleSupported to LegacyBackgroundApiService (#44240)
104ef3781d test(e2e): add BTC activity cluster spec (#43005)
7a647f51f8 feat(hardware-wallets): add signing page components (#43941)
13663f6db8 refactor: add TransactionController to wallet initialization (#43182)
7820bf530c chore: migrate getPhishingResult to LegacyBackgroundApiService (#44255)
c15b8dbeee refactor(analytics): migrate perps events (#43890)
4d33ee059f chore: migrate throwTestError to LegacyBackgroundApiService (#44239)
94614aba0f chore: migrate getAssets to LegacyBackgroundApiService (#44241)
4a9c03cbeb fix(perps): hide perps balance and position data when privacy mode is enabled (#44262)
93e14da37f fix: updated added to chainlist icon and padding (#44268)
480d4f821e fix: arc swap assets picker missing prices (#44073)
5825f03d69 feat(perps): gate terminal backend behind perpsTerminalBackendEnabled feature flag cp-13.39.0 (#43989)
03230d6229 test: fix flaky test MetaMask onboarding User can add custom network during onboarding (#44243)
5652b6cb1e feat(stellar): add trustline support in transaction history v3 (#44200)
d5ccb0e794 chore(e2e): scaffold bitcoin-regtest-up bootstrap for BTC E2E (#42943)
2ea4542077 fix: transaction id row (#44188)
aa5378721b fix: swap tx fails when smart account upgrade is required cp-13.39.0 (#44291)
a85e8a0380 chore: remove unused selectors (#44278)
de7420417a Merge pull request #44272 from MetaMask/stable-main-13.38.1
7c3e420839 chore(component-library): remove unused legacy icon SVGs (#44227)
698a384cbb fix(ramps): remove network gating from buy entry points (#44069)
7f534c5cda chore: New Crowdin Translations by GitHub Action cp-13.39.0 (#43689)
e07fedcb92 Merge origin/main into stable-main-13.38.1
33acc092d8 chore: upgrade design system packages (v52.0.0) (#44226)
83378bca32 perf(6556): remove redundant isEqual from awaiting-signatures useSelector calls (#44234)
4d12b0cc00 feat: added transition for settings page (#44074)
65c0fca156 fix(perps): truncate long asset names in market list to a single line cp-13.39.0 (#44214)
04afd3c489 perf: replace deep equality with shallow + add result equality to filter-based transaction selectors (#44110)
ecaa92746c perf(6916): refactor core UX selectors to remove deep-equality subscriptions (#44235)
0be73a9e7a fix(onboarding): updated min-height for login-option cp-13.39.0 (#44265)
9ef5547abe bump: upgrade @metamask/assets-controller to ^10.1.0 (#44246)
38571fa64d refactor(analytics): move event enrichment downstream (#44219)
da8373fef1 feat: use canonical_profile_id as a segment trait instead of profile_id (#44213)
af45d23d92 refactor(analytics): migrate multichain accounts events (#43896)
523715f346 feat(musd): tag prefilled_max input type on Transaction Added event (#44211)
0eab632cb3 chore: bind updateHiddenAccountsList directly to AccountOrderController:updateHiddenAccountsList (#44245)
3fb4d44298 chore: bind updateAccountsList directly to AccountOrderController:updateAccountsList (#44244)
0c644a4a55 chore: remove unused endTrace from getApi (#44237)
89add44149 chore: migrate toggleExternalServices to LegacyBackgroundApiService (#44143)
d4ce5e48ab chore(assets): add robinhood svg (#44191)
787b18b802 feat: Bump Snaps packages (#44210)
4253ff3e2e chore(6928): Replace react-beautiful-dnd with @hello-pangea/dnd (#43328)
8f9719a7d9 refactor(analytics): migrate smart transactions controller events (#43902)
2f843003ed feat(e2e): add Tron seeder asset helpers (#44150)
a93e640377 chore: removed old token import modal (#43712)
3d60c993a6 test: enhance clikElementSafe (#44236)
c4933e235a refactor(analytics): migrate multichain account chrome events (#43919)
fbd638ea2c refactor(analytics): migrate accounts hardware wallet events (#43895)
da0bbb6375 fix: disable CTA swap button for Tron when no network fees retrieved (#44107)
6639fdb7c8 fix: bignumber issues everywhere cp-13.38.1 (#44216)
ee138ca34d feat: scam questionnaire on malicious internal send flows (#43822)
c1bbdd9676 refactor(analytics): migrate token management assets events (#43912)
44008b9886 feat(e2e): add java-tron local node configuration (#44149)
a5ebebb3b0 feat: replace use metametrics with useAnalytics hook for networks page (#44212)
e53335e0c7 chore: set bottom nav bar conditional rendering (#44215)
82846bc6a1 feat: added BFT consolidation feature for new users (#43935)
8f31233a4f refactor(analytics): migrate assets events (#43889)
6dc7a8dad8 chore: bind alignMultichainWallets directly to MultichainAccountService:alignWallets (#44134)
09a4ab422b refactor(hardware-wallets): unify signing tracker (#43940)
1a2ca55143 chore: remove unused trackInsightSnapView from getApi (#44135)
d063aa9af5 chore: bump assets controller to v10.0.0 ASSETS-3385 (#44055)
f4819cfd9c chore: bump @metamask/bitcoin-wallet-snap to ^1.14.2, @metamask/solana-wallet-snap to ^2.10.0 (#44209)
fdd45f6033 refactor(analytics): migrate network and navigation chrome events (#43918)
c9b563c309 refactor(analytics): migrate modals and name display events (#43917)
3b6129124e refactor(analytics): migrate unlock and rewards events (#43916)
09da33f257 feat(e2e): add shared local node fixture plumbing (#44148)
ff56170604 test: Sync Feature Flag Registry - 2026-07-07 01:33 UTC (#44204)
cf8762c11f feat: sync wallets/accounts via MWP QR (#43711)
f23dee8a95 feat: Add UI components for Ledger status screens (#43720)
efd4b3f69d chore: clean up legacy Tag storybook (#44186)
1f603c3ba2 fix(confirmations): show Pay with row on initial MM Pay page (#44190)
481a27f030 feat(stellar): add Stellar chain utilities (#44192)
fa3a49e3f7 ci: make check-template-and-add-labels.mts run in Node 24 (#44056)
767bc86afe fix(swaps): fix stale search results after network filter change cp-13.39.0 (#44194)
0cd68d537a ci: fix "All jobs pass" in cross-repo PRs (#44182)
34e80bb6d1 feat: create bottom bar UI (#44197)
5125b602a9 perf(6645): refactor feature-specific selectors in home.component (#43577)
ba8bb54199 test: update wallet-fixture-export.spec.ts to the latest state and prevent drift with wallet-fixture-validation.spec.ts (#44127)
6aab821565 refactor(analytics): migrate keychain and SRP events (#43897)
5e03105fad test(e2e): add BTC assets cluster spec (#43006)
4821f0d027 refactor(analytics): migrate platform library background events (#43920)
d1ce52bc0f refactor(analytics): migrate core platform background events (#43901)
d7b3a92f70 test(e2e): cover completing a BTC to USDC (ERC20) swap (#43834)
3924472a09 fix: prevent Sentry storage read recursion (#44057)
5f73f93b46 Merge pull request #44172 from MetaMask/stable-main-13.38.0
1eb7182a53 Merge origin/main into stable-main-13.38.0
dd7c20db7e fix: disable gas sponsorship for hw wallets cp 13.39.0 (#44144)
f68939ba26 chore: bind updateNetworksList directly to NetworkOrderController:updateNetworksList (#44133)
21b8d0c67d chore: bind handleSnapRequest directly to SnapController:handleRequest (#44132)
37ddaa468a perf: memoize getUnconnectedAccounts selector (#44109)
75730ef0cd test: fix flaky test Ledger Hardware unlocks multiple accounts at once and removes one (#44094)
e5ee1c4b21 chore: setup codeownership of metamask-controller (#44131)
a4d0a59d15 chore: use delay on the global spinner (#44120)
cd82cd4c09 test: fix update-fixtures due to github policy change on actions cache (#44128)
72a4b94be4 refactor(analytics): migrate backup and sync account events (#43915)
535522dab6 chore: move aus e2e mocks out of auth CO scope (#44106)
a2014674f6 refactor(analytics): migrate shield and subscription events (#43893)
69c2aa4135 refactor(analytics): migrate onboarding welcome events (#43914)
a01132e83a refactor(analytics): migrate onboarding flow events (#43894)
63e37788f6 feat: source AddressBookController from @metamask/wallet@6.0.0 (#44112)
09dc5d616e refactor: remove deprecated "turn on notifications" modal (#44098)
3215860c6e chore: bind createNextMultichainAccountGroup directly to MultichainAccountService:createNextMultichainAccountGroup (#44103)
90f149a51a feat(swaps): integrate bridge QuoteStatusManager behind feature flag cp-13.39.0 (#44006)
a1c57e10d3 feat: update rbtc rootstock native icon (#44115)
c150be98df feat: add React Refresh to webpack watch builds (#43703)
184edd940c test: add automated RC build workflow for Extension, aligned with Mobile's workflow, aligns Extension RC notifications with Mobile (#42960)
d98ee34687 chore: upgrade design system packages (v50.0.0) (#44090)
3413101307 release: Bump main version to 13.40.0 (#44119)
8023b3c7f2 fix: bignumber incident 1752 cp-13.38.0 (#44097)
1c43659138 refactor(analytics): migrate send flow confirmation metrics (#43913)
8951ee1d47 refactor(analytics): migrate settings and privacy events (#43898)
b374c83130 refactor(analytics): migrate earn/mUSD events (#43888)
58c79c4cba test: fix update-fixtures script permissions (#44111)

Changelog (8 commits from main at RC cut)
Commit Description
27ee2a2b77 Merge pull request #44395 from MetaMask/release/13.39.2
311d329644 Merge branch 'stable' into release/13.39.2
19c20c50b9 Merge pull request #44342 from MetaMask/release/13.39.1
52e9d05e7c release: release-changelog/13.39.2 (#44394)
383e8dfbe9 fix: mv3 sw lavamoat background wrapping (#44187) (#44402)
c7383581ac release(runway): cherry-pick fix: Fix Firefox detatched-window memory leak by avoiding DocumentPictureInPicture instantiation in Snow hook cp-13.39.2 (#44401)
dab19fc117 bump semvar version to 13.39.2
05052d192c Merge pull request #44117 from MetaMask/release/13.39.0

AI Test Plan

Risk Score High Risk Medium Risk Files Changed Commits
48/100 4 7 1314 191
Cherry-Pick Scenarios (4)

High Risk Scenarios (1)

1. Token Management — Non-EVM token search/import (unified assets)

Risk Level: HIGH

Why This Matters: Cherry-pick 44361 fixes unified asset seeding for non-EVM search imports; a regression would break token discovery or show wrong metadata for non-EVM ecosystems.

Test Steps:

  1. Using a non-EVM account (e.g., Tron via Snap), open Import tokens and search for a known non-EVM asset; import it and verify symbol, icon, and decimals are correct and balance fetches.
  2. Perform the same search on an EVM account; verify results are scoped correctly (no non-EVM duplicates) and metadata remains accurate.
  3. Remove the imported non-EVM asset, refresh the account view, and re-import to confirm consistency.

Medium Risk Scenarios (3)

1. Networks — Add Robinhood Chain as a featured network

Risk Level: MEDIUM

Why This Matters: Cherry-pick 44346 adds a new featured network; misconfiguration (RPC, chain ID, currency) can prevent connections or cause users to transact on the wrong chain.

Test Steps:

  1. Open Add a network and verify Robinhood Chain appears under Featured with expected name/icon.
  2. Add and switch to Robinhood Chain; verify network banner shows correct chain name/currency and the account view loads without RPC errors.
  3. Connect a dapp while on Robinhood Chain and verify the reported chain ID and network name are correct; switch back to Ethereum and confirm the switch completes cleanly.

2. Activity — Duplicate pending transaction rows

Risk Level: MEDIUM

Why This Matters: Cherry-pick 44370 fixes an extra pending row from local state; duplicates confuse users and can lead to incorrect follow-up actions.

Test Steps:

  1. On an EVM network, submit a transaction that remains pending briefly; open Activity and verify only one pending entry is shown.
  2. Speed up or cancel the transaction; verify the list updates to one confirmed/cancelled entry with no duplicates.
  3. Reload or lock/unlock the extension; confirm no phantom pending rows reappear.

3. Security/UX — Scam questionnaire gated by LaunchDarkly flag

Risk Level: MEDIUM

Why This Matters: Cherry-pick 44582 gates the scam questionnaire behind a flag; incorrect gating could hide necessary education or inappropriately block critical flows.

Test Steps:

  1. With the LD flag Off, perform an action that previously surfaced the scam questionnaire (e.g., after a relevant risk trigger); verify the questionnaire does not appear and the flow continues normally.
  2. With the LD flag On (staging/dev), trigger the same flow; verify the questionnaire appears, completing or dismissing returns you to the prior screen without breaking navigation.
  3. Toggle the flag between runs and ensure the UI only reflects changes on the next trigger and never gets stuck in an in-between state.

Release Scenarios (7)

High Risk Scenarios (3)

1. State Migrations (Migration 216 + seedless onboarding data)

Risk Level: HIGH

Why This Matters: Migrations can corrupt user state (accounts, networks, tokens) or cause load failures; verifying upgrade integrity prevents data loss and broken post-upgrade flows.

Test Steps:

  1. On 13.39.x, create a new SRP wallet, add a second account, enable MetaMetrics, add a custom network (e.g., Arbitrum) and import at least one custom token.
  2. Upgrade the same profile to 13.40.0 and unlock.
  3. Verify all accounts are present, the previously selected network is preserved, token list and balances load without errors, and the Activity tab renders normally.
  4. Send a small native token transfer on the previously selected network and confirm it completes, with Activity updates reflected correctly.

2. Onboarding (Seedless/Passkey) flow and resume

Risk Level: HIGH

Why This Matters: New or migrated seedless onboarding state can get stuck or reset, blocking new users from completing setup or producing unusable accounts.

Test Steps:

  1. Fresh install 13.40.0 and start onboarding; choose the Seedless/Passkey (email/passkey) option if available and proceed to the authentication step.
  2. Close the extension mid-flow (e.g., close the popup or reload the extension), then reopen MetaMask.
  3. Confirm the onboarding resumes at the correct step rather than restarting; complete onboarding and land on the account view.
  4. Lock and unlock; sign a test message to confirm the created account is usable and persisted.

3. Analytics/MetaMetrics consent and event collection (controller refactor)

Risk Level: HIGH

Why This Matters: A refactor to analytics controllers/adapters risks silent failures, duplicate events, or privacy regressions that affect user trust and app stability.

Test Steps:

  1. In Settings > Security & privacy, turn MetaMetrics Off; with the browser DevTools Network tab open, switch accounts and navigate token details; verify no analytics/telemetry requests are sent.
  2. Turn MetaMetrics On and accept consent; repeat the same actions and verify exactly one analytics event per action (no duplicates).
  3. Lock and unlock or reload the extension; verify the consent state persists and you are not re-prompted unexpectedly.

Medium Risk Scenarios (4)

1. Token Management — Asset list sorting and search

Risk Level: MEDIUM

Why This Matters: Large UI changes to the asset list, control bar, and sort control can break discoverability, ordering, or persistence of user preferences.

Test Steps:

  1. On the Tokens tab with 5+ assets, open the sort control and switch between sorting by Balance and A–Z; verify the order updates correctly each time.
  2. Use the search field to filter to a specific token by name/symbol; verify the filtered list is correct.
  3. Clear the search; verify the full list returns and the previously selected sort order persists after navigating away and back.

2. Token Management — Inactive token badge and actions

Risk Level: MEDIUM

Why This Matters: A new inactive-asset badge surfaces risk to users; regressions could hide warnings or incorrectly block legitimate actions.

Test Steps:

  1. On the Tokens tab, locate any token labeled with an 'Inactive' badge (import one if needed) and open its details screen.
  2. Attempt Send and Swap from the inactive token’s details; confirm flows open and any warnings render correctly without blocking or crashing.
  3. Remove the token and re-import it; verify the 'Inactive' badge behavior is consistent and the token row renders stably.

3. DeFi portfolio list — empty state and protocol cells

Risk Level: MEDIUM

Why This Matters: UI changes to DeFi list cells and empty states can break navigation or misrepresent balances, confusing users about their positions.

Test Steps:

  1. Open Portfolio > DeFi; if you have no positions, verify the empty state copy/illustration render and the CTA link opens the correct destination in a new tab.
  2. With at least one DeFi position, verify protocol rows show correct protocol name, network, and value; click a row and confirm it opens the expected detail/external link.
  3. Switch networks and return to DeFi; verify the list refreshes without errors or stale data.

4. Network switching consistency with asset list

Risk Level: MEDIUM

Why This Matters: Wide UI and controller churn can cause cross-network state leakage or stale lists, leading to wrong balances or actions on the wrong chain.

Test Steps:

  1. Switch between Ethereum Mainnet and at least two other networks; verify the token list updates to the correct network scope (no stale tokens from prior network).
  2. Change the asset list sort on a non-Mainnet network, then switch back to Mainnet; verify sort preference persists appropriately.
  3. From a connected dapp, approve a network switch request; verify the UI shows the correct new network name/symbol and the asset list refreshes correctly.

Teams Sign-off Status

Signed off: None yet

Awaiting sign-off (5):
Assets, Networks, Onboarding, Security, Transactions


Generated by AI Test Plan Analyzer (gpt-5) at 2026-07-16T20:30:40.898Z

AI generated test plan (JSON): test-plan-13.40.0.json

This branch had an error being deployed

1 failed (outdated) and 3 inactive deployments
release-branch — 6d442d4d Deployed Jul 20, 2026 by vpintorico via Publish release #40
pr-comment — 6d442d4d Deployed Jul 16, 2026 by HowardBraham via Publish prerelease / Publish prerelease #152777
release-ci — 6d442d4d Deployed Jul 16, 2026 by HowardBraham via Publish prerelease / Generate AI test plan #152777
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

auto-rc-builds release-13.40.0 Issue or pull request that will be included in release 13.40.0 skip-benchmark-gate Disables `run-benchmarks/quality-gate` job team-bots Bot team (for MetaMask Bot, Runway Bot, etc.)

Projects

None yet

Development

Successfully merging this pull request may close these issues.