Skip to content

release: 13.53.0 - #46958

Merged
sleepytanya merged 53 commits into
stablefrom
release/13.53.0
Oct 19, 2026
Merged

sleepytanya merged 53 commits into
stablefrom
release/13.53.0

Conversation

@metamaskbot

@metamaskbot metamaskbot commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

🚀 v13.53.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
  • Bots Team
  • Confirmations
  • Core Extension UX
  • Delegation
  • Emerging Opportunities
  • Extension Platform
  • Money Movement
  • Networks
  • Onboarding
  • Perps
  • team-extension-ux
  • 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

LeVinhGithub and others added 30 commits October 1, 2026 19:12
<!--
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**

Stabilizes the flaky Multichain API E2E that adds an account from the
edit connected accounts screen before the account list is ready.

**Flake type:** Actions that Take Time

**Root cause:**

- The test opens the edit connected accounts screen and calls add new
account.
- The page-load check only waited for the header and the Save button.
- The Add account control sits in the account list, which can appear
after that check.
- The test then waited 10 seconds for the Add account label and clicked
once.
- On a slow run that control was not in the page yet, so the wait timed
out. The failure screenshot was taken after the timeout and already
showed Add account

**Solution:**

- Wait for an account name row in `checkPageIsLoaded`, so the account
list is on screen before the next step.
- Wait up to 20 seconds until Add account stays visible for 1 second,
then click it once. No retry-click and no fixed delay.
Slack:
https://consensys.slack.com/archives/CTQAGKY5V/p1790665207674129?thread_ts=1790584268.760419&cid=CTQAGKY5V

## **Changelog**

CHANGELOG entry: null

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

Fixes:
-->

## **Manual testing steps**

1. Ensure a Flask test build is running (`yarn start:test:flask`).
2. Run:

```bash
SELENIUM_BROWSER=chrome yarn test:e2e:single test/e2e/flask/multichain-api/evm/wallet_invokeMethod.spec.ts --debug --leave-running
```

3. Confirm `Should match selected method to the expected output` passes
(remove `it.only` before commit/PR).

## **Screenshots/Recordings**

<img width="400" height="619" alt="image"
src="https://github.com/user-attachments/assets/b39f8aad-c4c8-4c37-ada3-3c45615ffe91"
/>


### **Before**

Three CI failure screenshots from the same run:

1. Extension home: Account 1, banner "Still connecting to Localhost
8545... Update RPC", balance 25 ETH, Tokens tab, Network Localhost 8545.
2. Multichain test dapp: scopes eip155:1337, eip155:1338, eip155:1000
and two CAIP addresses added. Console error "Error creating session:
Error: Request timeout".
3. MetaMask dialog "Select accounts": Wallet 1, Account 1 checked
($75,250.00), blue "Add account" with a plus icon, black Save button.
This is the screen where the test timed out waiting for the add-account
control.

### **After**

No product UI change. The test waits for an account row on the
edit-accounts screen, then waits until the Add account button stably
shows "Add account", then clicks it once.

<!--
## **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**
> E2e page-object timing only; no production or wallet logic changes.
> 
> **Overview**
> Fixes flaky Multichain API E2E when adding an account from the edit
connected accounts screen by tightening **when** the test considers the
UI ready and **how** it waits before clicking Add account.
> 
> **`checkPageIsLoaded`** now also waits for at least one account name
row (`anyAccountName`), not just the header and Save/Connect footer—so
the account list (and the Add account control inside it) is on screen
before **`addNewAccount`** runs.
> 
> **`addNewAccount`** replaces a single 10s `waitForSelector` with a 20s
`waitUntil` that requires the Add account button to stay present and
visible for 1s (`stableFor`), then clicks once.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
097fce5. 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**

Stabilize the notifications enable E2E that times out while waiting for
the Accounts list Add wallet button after identity onboarding.

**Flake type:** Actions that Take Time

**Root cause:**

- The test finishes onboarding, then opens the Accounts list to add a
second account.
- Home only checks that account sync has succeeded at least once. That
flag stays true even while a later sync is still running.
- The Accounts screen still shows "Syncing..." and the Add wallet button
stays disabled.
- The test waits only 15 seconds for that button to stay enabled. Sync
can take longer (the identity wait allows 45 seconds), so the wait times
out.

**Solution:**

- After onboarding in this spec, wait until account-tree sync is idle
before opening Accounts, so the menu is not opened while a sync is still
running.
- In the shared identity onboarding flow, wait until sync is idle after
the "synced at least once" check, so callers leave Home only when sync
has finished.
- Raise the Accounts list sync wait from 15 seconds to 45 seconds so it
matches the identity sync budget.

SLack:
https://consensys.slack.com/archives/CTQAGKY5V/p1790670778065499?thread_ts=1790670317.922329&cid=CTQAGKY5V
<!--
## **Related pull requests**
-->

## **Changelog**

CHANGELOG entry: null

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

Fixes:
-->

## **Manual testing steps**

1. Ensure a Chrome test build is available (`yarn start:test`).
2. Remove `it.only` from the failing test before committing or opening a
PR.
3. Run:

```bash
SELENIUM_BROWSER=chrome yarn test:e2e:single test/e2e/tests/notifications/enable-notifications.spec.ts --debug --leave-running
```

## **Screenshots/Recordings**

<img width="401" height="493" alt="image"
src="https://github.com/user-attachments/assets/445f1e28-6ea8-4b69-96dd-bd2a5a703a9b"
/>


### **Before**

1. Accounts screen at the timeout: header "Accounts", search field
"Search your accounts", Account 1 with address 0xAa417...7405a, a
spinner plus the text "Syncing...", and a gray disabled pill button also
labeled "Syncing...". The Add wallet control is not enabled.

2. Earlier Home screen from the same run, before the Accounts list
opened: "Fund your wallet", "Add funds", Buy / Swap / Send / Receive,
tabs Tokens / Perps / DeFi / NFTs / Activity, same account address
0xAa417...7405a.

### **After**

No product UI change. After onboarding, the test waits until
account-tree sync is idle before opening Accounts, and the Accounts list
sync wait is 45 seconds instead of 15.

<!--
## **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**
> Test and page-object timing only; no production wallet or notification
behavior changes.
> 
> **Overview**
> Fixes flaky **enable notifications** E2E timeouts when the Accounts
list still shows **Syncing...** and keeps **Add wallet** disabled after
identity onboarding.
> 
> After onboarding, tests now call **`waitUntilAccountTreeSyncIdle`** so
navigation to Accounts happens only when account-tree sync is
finished—not merely after “synced at least once,” which can stay true
while a later sync runs. That wait is wired into
**`completeOnboardFlowIdentity`** and again in the notifications spec’s
**`onboardAndAddAccount`** helper before opening the account menu.
> 
> **`AccountListPage`** defaults for
**`waitForAddWalletButtonStablyReady`** and
**`waitUntilSyncingIsCompleted`** move from **15s** to
**`BASE_ACCOUNT_SYNC_TIMEOUT` (45s)**, aligned with the identity sync
budget.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
5564a87. 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**

Adds `continue-on-error: true` to every AWS OIDC job, so we can at least
see builds and tests while this is being repaired.

Adds an explicit "Temporary OIDC workaround always fail"

## **Changelog**

CHANGELOG entry: null

<!--## **Related issues**
## **Manual testing steps**
## **Screenshots/Recordings**
## **Pre-merge author checklist**
## **Pre-merge reviewer checklist**-->

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **High Risk**
> The CI status gate is forced to fail on every run, which blocks merge
until reverted; S3 uploads and prerelease PR comments may fail silently
while OIDC is down.
> 
> **Overview**
> **Temporary CI relief while AWS OIDC is broken:** artifact uploads and
related token steps no longer fail the jobs that produce builds, tests,
and benchmarks.
> 
> `continue-on-error: true` is added on every `upload-s3` step touched
in this PR (Storybook, TS migration dashboard, main bundle-size,
prerelease test plan, audit baseline, benchmark matrices, and
build/bundle-analyzer uploads in `run-build.yml`). Prerelease publishing
also applies it to the `get-token` step used for PR build announcements,
so a token exchange failure skips the announce step instead of killing
the job.
> 
> **Separately**, `ci-status-gate.yml` gains a first step **"Temporary
OIDC workaround always fail"** that runs `exit 1`, so the aggregate **CI
status gate** job fails immediately on every run (before the usual “all
jobs passed” logic). That keeps the required gate red until this
workaround is removed, even when builds and tests are green.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
4796788. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…46925)

## **Description**

Reverts #46881, now that AWS OIDC is working
again

## **Changelog**

CHANGELOG entry: null

## **Related issues**

N/A

## **Manual testing steps**

N/A

## **Screenshots/Recordings**

N/A

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

- [ ] 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.
## **Description**

Follow-up to #46530 and [the shared host-check review
comment](#46530 (comment)).

The browser request filter and trusted-content deep-link resolver
previously accepted subdomains of configured deep-link hosts. This PR
limits both to the exact configured hosts (`link.metamask.io` and
`link.metamask.com` by default). Subdomain URLs are no longer
intercepted by the router or resolved as internal routes from trusted
content; they remain external URLs and do not enter the extension's
deep-link interstitial flow. Supported links on the configured hosts
retain the existing interstitial policy.

Move the host predicate and constants into `common.ts`, and reuse the
exact-host check for home QR deep-link actions while retaining their
HTTPS, default-port, and pathname requirements. Update router, helper,
carousel, and home-action tests for the exact-host policy.

## **Changelog**

CHANGELOG entry: Restricted deep-link handling to configured hosts
instead of their subdomains.

<!--
## **Related issues**
No separate issue; stacked on #46530.
-->

## **Manual testing steps**

1. Build and load the extension from this branch.
2. Open an unsigned supported deep link on `https://link.metamask.io`
and `https://link.metamask.com` in a new tab; verify each opens the
security interstitial.
3. Open the same path on `https://invalid.link.metamask.io` or
`https://invalid.link.metamask.com`; verify the extension does not
intercept the navigation or open its interstitial. The destination site
may show an error if the subdomain does not exist.
4. Open the home route with a `predictDeeplinkUrl` pointing to
`https://link.metamask.com/predict`; verify the QR action appears.
Repeat with `https://invalid.link.metamask.com/predict` or
`https://link.metamask.com:444/predict` and verify it does not appear.
5. Click a trusted-content carousel slide linking to a supported route
on an exact configured host and verify internal navigation; repeat with
an invalid subdomain and verify it opens as an external URL.

<!--
## **Screenshots/Recordings**
### **Before**
### **After**
No visual layout change.
-->

## **Pre-merge author checklist**

- [x] I followed MetaMask coding standards and completed the PR
template.
- [x] I included tests for the host checks and affected UI flows.
- [ ] I applied the appropriate labels, if needed.

<!--
## **Pre-merge reviewer checklist**
- [ ] Manually tested and confirmed acceptance criteria.
-->

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **High Risk**
> This tightens a security boundary across interception, interstitial
bypass, and QR deeplink acceptance; misconfiguration could break
legitimate links, while the change reduces subdomain takeover/phishing
risk.
> 
> **Overview**
> Deep-link interception and trusted-content resolution no longer treat
**subdomains** of `link.metamask.io` / `link.metamask.com` as MetaMask
links. Only those exact hostnames are handled; URLs like
`https://invalid.link.metamask.io/...` stay normal external navigations
(no extension router, no interstitial, no in-app route rewrite).
> 
> The background **`webRequest`** filter changes from `*://*.${host}/*`
to `*://${host}/*`, and **`isDeepLinkHost`** switches from
suffix/subdomain matching to an exact list membership check. Shared
symbols move from **`constants`** to **`common`**, and home QR deeplink
validation reuses **`isDeepLinkHost`** with **HTTPS on the default
port** plus pathname checks.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
0571886. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Deep links on `link.metamask.com` can be signed for their own origin.
Keep verification of legacy `.io` signatures first, then try other
configured signing hosts only for exact, configured HTTPS deep-link
hosts. Preserve the canonical path and signed query while swapping the
signing origin. Includes tests for `.io`, `.com`, lookalike hosts,
HTTP/port restrictions, and signed query parameters.

Stacked on #46748. Security team authorization was confirmed by the
requester in the working conversation for this change.

## **Changelog**

CHANGELOG entry: Fixed signature verification for deep links signed with
configured MetaMask domains.

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

Fixes:
-->

## **Manual testing steps**

1. Load the extension from a test build and open a signed
`link.metamask.com` deep link whose signature was generated for
`link.metamask.com`; verify it resolves to the intended route.
2. Open an existing `.io`-signed deep link on both `link.metamask.io`
and `link.metamask.com`; verify both continue to resolve.
3. Open invalid or unsigned links from an untrusted origin; verify the
security interstitial still appears.
4. Open a link on a lookalike hostname or an HTTP URL; verify it is not
accepted as an alternate signed-host link.

<!--
## **Screenshots/Recordings**

### **Before**

### **After**
-->

## **Pre-merge author checklist**

- [x] I've followed the MetaMask Contributor Docs and MetaMask Extension
Coding Standards.
- [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 if applicable.
- [ ] I've applied the right labels on the PR, if applicable.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR.
- [ ] I confirm that this PR addresses all acceptance criteria and
includes the necessary testing evidence.
## Version Bump After Release

This PR bumps the main branch version from 13.52.0 to 13.53.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.52.0` to `13.53.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.52.0
- Release branch: release/13.52.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>
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## **Description**

Several E2E page objects and shared helpers used fragile locators that
matched generic HTML tags (`button`, `p`, `h1`, `h2`, `div`) combined
with visible text. These selectors are brittle because unrelated
elements with the same tag and text can appear elsewhere in the DOM, and
they do not follow the project's preference for `data-testid`-based
locators.

This PR replaces those generic tag selectors with stable `data-testid`
locators that already exist in the UI.

**Problem areas addressed:**
- Homepage primary CTAs (Buy, Send, Receive, Swap) used `{ css:
'button', text: '...' }`
- Global menu Snaps entry used `{ text: 'Snaps', tag: 'div' }`
- Confirmation flows used `{ css: 'p' }` / `{ css: 'h2' }` for gas
details, titles, and transaction detail rows
- Account/details modals used generic `button` + text selectors where
test IDs exist
- Critical error and change-password warning pages used generic
heading/paragraph selectors

**Solution:**
- Use suffix-matching test IDs for EVM/non-EVM homepage buttons (e.g.
`[data-testid$="-overview-send"]`)
- Use confirmation-specific test IDs (`confirm-title-text`,
`transaction-details-recipient-row`, `edit-gas-fees-row`, etc.)
- Use modal/component test IDs for account details, address modal, and
password warning flows
- Handle Receive on non-EVM homepages by opening the More menu when
Receive is not on the primary action row

**Merge with main:**
- Merged latest `main` and resolved modify/delete conflict by accepting
removal of `dialog/account-details-modal.ts` (account details flows now
live in `accounts/details-page.ts` with existing test IDs).

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

1. Run the extension test build (already in watch mode locally).
2. Run a subset of affected E2E specs to verify selectors resolve
correctly:
- `yarn test:e2e:single test/e2e/tests/btc/account-derivation.spec.ts
--browser=chrome`
- `yarn test:e2e:single test/e2e/tests/tron/account-derivation.spec.ts
--browser=chrome`
- `yarn test:e2e:single
test/e2e/tests/confirmations/transactions/erc20-approve.spec.ts
--browser=chrome`
- `yarn test:e2e:single test/e2e/tests/send/send-eth.spec.js
--browser=chrome`
3. Confirm homepage Send/Swap/Receive/Buy buttons are found and
clickable in any home-flow test.
4. Confirm transaction confirmation advanced gas details assertions pass
after toggling advanced details.

<!--
## **Screenshots/Recordings**
### **Before**
### **After**
-->

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<div><a
href="https://cursor.com/agents/bc-a4329bc2-a68a-41f3-99d5-06d190fa3698?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-a4329bc2-a68a-41f3-99d5-06d190fa3698&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

---------

Co-authored-by: Cursor Agent <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**

The add-network confirmation screen showed RPC URLs with Unicode
homograph hostnames and did not warn when the chain was not on the safe
list. Wire existing `isValidASCIIURL` / `toPunycodeURL` helpers: show
the punycode host in the RPC row and emit `networkUrlErrorWarning` on
that row before safe-chain validation.

## **Changelog**

CHANGELOG entry: fix: add-network confirmations so homograph RPC
hostnames show a warning

## **Related issues**

Fixes: MetaMask/MetaMask-planning#7612

## **Manual testing steps**

1. Load the extension and connect a test dapp.
2. Call `wallet_addEthereumChain` with an RPC URL whose hostname uses
confusable Unicode (e.g. `https://iոfura.io/v3/...` with Armenian `ո`
instead of ASCII `n`).
3. On the add-network confirmation, confirm the RPC row shows
`xn--ifura-dig.io` (not the spoofed Unicode) and a warning on the RPC
row with the punycode URL.
4. Repeat with a normal ASCII RPC URL and confirm there is no homograph
warning.

## **Screenshots/Recordings**

### **Before**

Homograph RPC hostname shown as-is; no RPC-row warning for unrecognized
chains.

### **After**

Punycode hostname in the RPC row; RPC-row warning with punycode version.

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes add-network confirmation security UX (RPC display and
warnings) where users decide which endpoint to trust; logic mirrors
existing helpers used in the legacy template.
> 
> **Overview**
> **Add-network confirmations** now treat IDN homograph RPC hostnames
like the legacy template: the RPC row shows the **punycode** hostname
(not confusable Unicode), and a **warning** is raised on that row via
`networkUrlErrorWarning` even when the chain is not on the safe list.
> 
> `useAddEthereumChainAlerts` runs `isValidASCIIURL` on
`requestData.rpcUrl` before safe-chain checks and emits
`rpcUrlIdnHomograph` on the RPC field. Tests cover punycode display and
the homograph alert.
> 
> `networks-page.test.tsx` only stabilizes Chainlist/search tests by
using `fireEvent.change` plus `waitFor` instead of `userEvent.type`.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
30e4c21. 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**
There's an intermittent issue where the snap simple keyring crashes,
thus making the tests flaky.
We change the specs to tolerate failure mode, until the issue is fully
resolved/investigated.
We'll work on supporting more debug logs a a separate task

Bug ticket: #44026
Slack context:
https://consensys.slack.com/archives/CTQAGKY5V/p1790584268760419

## **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. Check ci -- no failure in those test should cause the ci job to fail

## **Screenshots/Recordings**

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

### **Before**


<img width="2462" height="606" alt="image"
src="https://github.com/user-attachments/assets/f166b436-bf02-429e-8bfc-6a85492f5dd1"
/>

<img width="780" height="493" alt="image"
src="https://github.com/user-attachments/assets/9d5d44aa-bed1-4ec3-a646-091fc73b5b00"
/>

<!-- [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 CI behavior change; no production or runtime logic is
modified.
> 
> **Overview**
> Snap Simple Keyring e2e coverage is isolated into **tolerate-failure**
specs so intermittent snap keyring crashes no longer fail CI, while the
tests still run and failures are logged.
> 
> The multichain **“should display wallet for Snap Keyring”** case moves
from `multichain-account-list-menu.spec.ts` into
`multichain-account-list-menu-snap-keyring.tolerate-failure.spec.ts`;
the main multichain menu spec drops that scenario and related snap-only
imports. Comments are added on existing `*.tolerate-failure.spec.ts`
files noting that `run-e2e-test.js` treats paths containing
`tolerate-failure` as non-blocking.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
d2a0cbe. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Adds instrumentation for homepage critical user flow which is currently
blank. This tracks balance and token list ready. A helper hook was added
and uses existing trace wrappers and handles lifecycle completion,
cleanup, etc.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: 

Related: CEUX-1356

## **Manual testing steps**

1. Unlock the extension and open the homepage.
2. Switch accounts and enabled networks, including a testnet.
3. Verify the balance-ready and token-list-ready traces are emitted with
`success` and `content_state` attributes.

## **Screenshots/Recordings**

Not applicable.

### **Before**

Not applicable.

### **After**

Not applicable.

## **Pre-merge author checklist**

- [x] I've followed MetaMask Contributor Docs and Extension Coding
Standards.
- [x] I've completed the PR template to the best of my ability.
- [x] I've included tests where applicable.
- [x] I've documented code using JSDoc format where applicable.
- [x] I've applied the appropriate labels.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR.
- [ ] I confirm that this PR addresses the acceptance criteria and
includes necessary testing evidence.

## **Validation**

- Changed-file ESLint passed.
- Focused Jest tests passed: 3 suites, 29 passed, 1 skipped.
- oxfmt passed.
- git diff --check passed.



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Observability-only changes with bounded Sentry sampling; minor balance
loading-state tweak in coin overview with no auth or payment impact.
> 
> **Overview**
> Adds **homepage performance tracing** so Sentry can measure when the
wallet home is “ready” and when key sections show content.
> 
> Introduces **`useTrace` / `useLayoutTrace`** and a
**`TraceCoordinator`** that runs a parent **`Homepage Ready`**
transaction until required child signals (`balance`, `tokens`) complete.
**`useCoordinatedTrace`** emits nested **`Homepage Section Time To
Content`** spans with `section_id`, `content_state` (filled/empty), and
snake_cased attributes via new **`toSnakeCase`**.
> 
> Wires this into **`AccountOverviewLayout`**, **`CoinOverview`**
(balance ready after loading/empty-state logic, with a
**`generationKey`** on account/network changes), and **`TokenList`**.
Adds trace names/ops, a selector
**`getSelectedAccountGroupNetworkGenerationKey`** for stable parent
trace IDs, and **0.1% Sentry sample rates** for the new transaction
names.
> 
> **`coin-overview`** also tightens zero-fiat balance loading so the
skeleton stays up until delay state is in sync when networks or delay
flags change.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
3326750. 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**

(Behind a feature flag)

Adds a MetaMask ticker widget for supported token `$SYMBOL`s on X.
Supported tokens display live market data and open a widget with token
details and actions to open the asset or swap flow in MetaMask.

The widget runs in an extension iframe rather than rendering its React
tree directly into the host page. Background handlers own token search,
price history, navigation, preference updates, and feature availability.
This change also adds the required extension manifests, Webpack entries,
LavaMoat configuration, settings preference, and threat model.

## **Changelog**

CHANGELOG entry: Added x.com ticker widget

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

Fixes:
-->

## **Manual testing steps**

1. Load the extension and sign in to X.
2. Open a post containing a supported cashtag, such as `$BTC`, and
verify the cashtag displays its current price and 24-hour change.
3. Hover or focus the cashtag and verify the widget opens with token
details and a price chart.
4. Verify the asset-details and swap actions open the expected MetaMask
route in both popup and side-panel modes.
5. Open a cashtag with multiple matching assets, select **View similar
tokens**, and verify the results table appears.
6. Disable the ticker widget from its menu, confirm the dialog, and
verify cashtags return to their standard X appearance.
7. Re-enable the ticker widget from **Settings → Preferences and
display** and verify the enhanced cashtags return.

## **Screenshots/Recordings**

### **Before**

Standard X cashtags render as plain links.

### **After**

|Pill|Widget|
|---|---|
|<img width="169" height="52" alt="image"
src="https://github.com/user-attachments/assets/ee9d8cbf-f7b8-433b-a5ad-4c91a4173658"
/>|<img width="575" height="444" alt="image"
src="https://github.com/user-attachments/assets/3fb68938-5c45-4985-a00f-4eb2202f6062"
/>|

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **High Risk**
> Introduces third-party page injection on x.com, relaxed CSP
frame-ancestors, and new runtime messaging that opens swap/asset
flows—security-sensitive surface area despite sender checks and feature
gating.
> 
> **Overview**
> Adds a **feature-flagged MetaMask ticker widget on X** that enhances
`$SYMBOL` cashtags in tweets with live price pills and a hover/focus
popover, without injecting the full React UI into the host page.
> 
> **On-page behavior:** An X content-script path scans tweet cashtag
links, resolves tokens via background messaging, and injects styled
pills plus a shadow-DOM popover anchored to the clicked cashtag. The
popover loads a new web-accessible `cashtag-widget.html` iframe that
renders token details, a 1D price chart, similar-token picker,
swap/view-details actions, and disable-with-confirmation.
> 
> **Background & policy:** A new cashtag background bridge validates
message senders (X top frame vs widget iframe), gates on Basic
Functionality + `cashtagInjection` + `showTickerWidget`, fetches token
search and price history from MetaMask APIs, broadcasts enable/disable
to X tabs, tracks widget analytics, and opens swap/asset routes in side
panel, popup, or tab. Manifest/CSP updates expose the widget HTML to
`x.com` and allow framing from X; disabling external services now clears
`showTickerWidget`.
> 
> **Build/tooling:** Webpack treats cashtag page CSS as injectable
strings, builds widget CSS with inlined design tokens, registers
isolated HTML/LavaMoat lockdown for the iframe bundle, and adds
extensive unit tests plus a shared overflow menu component.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
25a0768. 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**

The Perps market list re-sorted itself on every live price tick, so rows
swapped places while being read. Sorting by 24h price change was the
worst case, because the ranking runs on `change24hPercent` — the exact
field the price stream rewrites several times a second.

`usePerpsLiveMarketListData` returns a fresh `markets` array on every
tick with `price` and `change24hPercent` overwritten. `displayedMarkets`
listed `allMarkets` as a dependency and called `sortMarkets` inside it,
so every tick produced a new ranking and re-rendered the rows in a new
order.

This separates filtering from ranking. Filtering still tracks live data.
The row order is established from a snapshot and then held: a new order
is computed only when the user changes what the ranking means (sort
field, sort direction, category filter, search query) or when the set of
matching markets itself changes. Live values are projected onto that
frozen order, so prices and percentages keep updating in place while
rows stay put.

Four tests cover it: the order holds across a tick that would re-rank,
values still update on a row that has not moved, changing the sort
re-ranks on the ticked values rather than the stale snapshot, and a
newly listed market is ranked into position rather than appended.

One thing to look at in review: `rankingSnapshot` is a deliberately
stale memo carrying an `eslint-disable` for
`react-hooks/exhaustive-deps`. Reading current markets through a ref
instead is rejected by this repo's `react-hooks/refs` rule ("Cannot
access refs during render"), and adding `matchingMarkets` back as a
dependency reintroduces the bug. The comment above it says so.

## **Changelog**

CHANGELOG entry: Fixed the Perps market list reordering rows while live
prices updated

## **Related issues**

Fixes:
[TAT-3934](https://consensyssoftware.atlassian.net/browse/TAT-3934)

## **Manual testing steps**

1. Open the Perps market list.
2. Sort by Price change.
3. Watch for 30 seconds without touching anything. Percentages and
prices should keep updating; no row should change position.
4. Change the sort field or direction. The list should immediately
re-rank on the values currently on screen, not on the values from when
the page was opened.
5. Switch category filters, then type in search. Each should produce a
correctly ordered list.
6. Repeat with Volume, Open interest and Funding rate to confirm nothing
regressed.

## **Screenshots/Recordings**

### **Before**

Recording of the current behavior is attached to
[TAT-3934](https://consensyssoftware.atlassian.net/browse/TAT-3934).

### **After**

Video shows DASH and PEOPLE hold their sort even after PEOPLE's price
change exceeds DASH's. Only after we resort do they swap position in the
UI.

https://www.loom.com/share/44de2b59cd1b4e9aa3fd69622caf0f23

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


[TAT-3934]:
https://consensyssoftware.atlassian.net/browse/TAT-3934?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes core market-list ordering logic for live streams; wrong
ranking keys could show stale order or miss re-ranks when markets appear
or go live.
> 
> **Overview**
> **Stops the Perps market list from re-sorting on every live price
tick** while still updating prices and 24h change in place—fixing rows
jumping under the reader when sorted by price change.
> 
> Filtering/search still tracks live `allMarkets`; **row order is
frozen** until the user changes sort, filter, or search, the set of
matching symbols changes, or the stream first goes live (`isLive`). A
`rankingSnapshot` captures markets at those moments; `displayedMarkets`
maps the frozen symbol order onto current live values.
> 
> Adds a **“row order under live updates”** test suite (stable order
across ticks, in-place value updates, re-rank on sort change / new
listings / first live tick).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
a6624c3. 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 5 <noreply@anthropic.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Stellar was missing from send loader config. 

<!--
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: Added stellar in send loader config

## **Related issues**

Fixes: #46812

## **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 parity fix in confirmation routing logic with a matching test;
no auth or payment changes.
> 
> **Overview**
> **Fixes Stellar send confirmations not auto-opening** by treating
`STELLAR_WALLET_SNAP_ID` like Bitcoin, Solana, and Tron in the send
confirmation `Loader`.
> 
> When an unapproved templated confirmation comes from the Stellar
wallet snap, the loader now redirects to the v-next confirmation route
(`CONFIRMATION_V_NEXT_ROUTE/{id}`) instead of staying on the loading
screen. A unit test mirrors the existing Bitcoin/Solana cases for
Stellar pending sends.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
141a6bc. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…46862)

## **Description**

Money account deposit funnels filter transaction events on
`transaction_type = money_account_deposit`, but those deposits are
submitted with `addTransactionBatch`. The parent type is `batch`, so
Transaction Added, Submitted, and Finalized were recorded as `batch`.

This matches mobile: `getTransactionTypeValue` checks nested transaction
types before falling back to the parent type. A deposit batch now
reports `money_account_deposit`, and a withdrawal batch reports
`money_account_withdraw`. Other batches still report `batch`.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/CONF-2117

## **Manual testing steps**

1. Build the extension and load it in Chrome.
2. Open the money account and start a deposit. Confirm it with a pay
token selected.
3. In the MetaMetrics debugger, inspect Transaction Added, Transaction
Submitted, and Transaction Finalized for that confirmation.
4. Verify `transaction_type` is `money_account_deposit`.
5. Repeat a money account withdrawal and verify `transaction_type` is
`money_account_withdraw`.
6. Confirm an unrelated batch transaction and verify `transaction_type`
is still `batch`.

<!--
## **Screenshots/Recordings**
### **Before**
### **After**
-->

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Analytics-only classification change in transaction metrics context;
no transaction submission or signing logic is modified.
> 
> **Overview**
> **Transaction metrics** now classify money account pay flows correctly
when they are submitted as batches (`addTransactionBatch`), instead of
emitting `transaction_type: batch`.
> 
> `determineTransactionTypeAndContractInteraction` inspects nested
transactions via `hasTransactionType` and maps deposits and withdrawals
to `money_account_deposit` and `money_account_withdraw`, aligned with
mobile’s `getTransactionTypeValue`. Unrelated batches still report
`batch`, and **retry** paths pass through the same nested lookup so
retried deposit batches keep the money-account type.
> 
> Unit tests cover batch approve+deposit, withdraw-only batches, direct
money account types, non-pay batches, and retried deposit batches.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
cb4e76d. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Returning from Add funds on Earn on your crypto left two identical Earn
entries in history. The deposit confirmation is pushed on top of that
page, and back replaced the confirmation entry with the same URL, so the
first in-app back press stayed on Earn and only the second press reached
Money home.

Pushed confirmations (Money deposit and withdraw) now record
`goBackAction=pop`. Back and auto-exit pop that history entry when there
is already an in-app page underneath. Flows that open the confirmation
with replace, such as Perps deposit and mUSD conversion, still return by
replacing the entry with `goBackTo`. A confirmation that is the first
history entry also still replaces, so a notification window does not
navigate out of the extension.

## **Changelog**

CHANGELOG entry: Fixed the back arrow on Earn on your crypto requiring
two taps after adding a token

## **Related issues**

Fixes:
[CONF-2115](https://consensyssoftware.atlassian.net/browse/CONF-2115)

Fixes: #46672

## **Manual testing steps**

1. Run the extension and open Money.
2. In Earn on your crypto, click View all.
3. Click Add on any token.
4. Click the back arrow on the add-funds confirmation.
5. On Earn on your crypto, click the back arrow once.
6. Confirm you return to Money home on that first press.
7. Repeat from Money home using Add funds, then back, and confirm one
back press leaves the confirmation for the page you started from.
8. From a Perps order screen, open Add funds and press back. Confirm you
return to the order screen in one press.

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

[CONF-2115]:
https://consensyssoftware.atlassian.net/browse/CONF-2115?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes shared confirmation exit navigation used by cancel, auto-exit,
and Money/Perps flows; behavior is well covered by new tests but
incorrect edge cases could still affect back-stack UX across
wallet-initiated confirmations.
> 
> **Overview**
> Fixes broken in-app back navigation after leaving **pushed**
transaction confirmations (e.g. Money Earn add funds), where exiting
always **replaced** the confirmation with `goBackTo` and duplicated the
origin route in history.
> 
> Pushed entry points now tag the URL with **`goBackAction=pop`**
(`navigateToTransaction`), and a shared **`navigateConfirmationExit`**
decides whether to **`navigate(-1)`** or **`replace` with `goBackTo` /
home** using the captured `goBackAction` and React Router `location.key`
(`default` still replaces so notification windows do not leave the
extension). **Confirm context** auto-exit and **`useConfirmActions`
cancel/back** use this helper; cancel with `navigateBackToPreviousPage`
also **suppresses auto-exit** to avoid double navigation. Flows that
open confirmations with **replace** (Perps deposit, mUSD) stay on the
replace path when `goBackAction` is absent.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
493f66a. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

When the MetaMask side panel defers the Ledger connect flow to the
expanded tab, it stayed on the add-wallet screen after account selection
finished, instead of returning to a sensible screen.

This PR navigates the side panel to the default route at handoff so it
lands on home once the hardware wallet flow completes in the expanded
tab:

-
`ui/pages/multichain-accounts/choose-new-wallet-type/choose-new-wallet-type-page.tsx`:
after handing off the hardware wallet flow with `keepWindowOpen` (side
panel), call `navigate(DEFAULT_ROUTE)`. The popup is unaffected because
it closes itself on handoff and needs no navigation.
- `choose-new-wallet-type-page.test.tsx`: added a unit test asserting
the side panel navigates to `DEFAULT_ROUTE` on handoff.

Refs:
[MUL-2231](https://consensyssoftware.atlassian.net/browse/MUL-2231?atlOrigin=eyJpIjoiY2I3MTUyMzYzZDNmNDU1ZGE2MzM5MjMyYTI0NDcwNDMiLCJwIjoiaiJ9)

## **Changelog**

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

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

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

CHANGELOG entry: Fixed a bug that was leaving the MetaMask side panel on
the add-wallet screen after connecting a hardware wallet in the expanded
tab.

## **Related issues**

Fixes: MUL-2231

## **Manual testing steps**

1. Run the extension (`yarn start`) and load it in Chrome.
2. Open MetaMask via the side panel UI.
3. In the side panel, go to the account menu → Add a new wallet, so you
land on the "choose new wallet type" screen.
4. Select **Hardware wallet** — the flow hands off to the expanded tab
with the Ledger connect screen.
5. Complete (or cancel) account selection in the expanded tab, then look
back at the side panel.
6. Verify the side panel now shows the home screen (default route)
instead of staying on the add-wallet screen.
7. Repeat steps 2–4 using the popup UI: verify the popup closes itself
on handoff and the behavior is unchanged.

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


[MUL-2231]:
https://consensyssoftware.atlassian.net/browse/MUL-2231?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Small, side-panel-only navigation after an existing browser handoff;
popup and fullscreen paths are unchanged.
> 
> **Overview**
> Fixes side panel UX when **Hardware wallet** opens the connect flow in
an expanded tab: the panel used to stay on the add-wallet screen after
handoff.
> 
> After `openExtensionInBrowser` with `keepWindowOpen` (side panel
only), the choose-new-wallet-type page now calls
`navigate(DEFAULT_ROUTE)` so the panel shows home while Ledger setup
runs in the tab. Popup handoff is unchanged (no extra navigation).
> 
> Tests cover side panel navigation to `DEFAULT_ROUTE` and assert popup
mode does not navigate there.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
1431737. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…46840)

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

Fixes Arc `USDC` handling in the Swap asset picker.
Arc’s native `USDC` balance is stored under the native `slip44` asset
representation, while Swaps must use the validated ERC-20 wrapper token.
The asset picker now keeps the native Arc asset hidden from the visible
list, but still uses it as a balance source for the ERC-20 `USDC` entry
shown in Swap.
Also updates the asset details navigation from the Swap asset picker so
clicking the `i` icon for Arc USDC opens the native Arc asset details
route.
This makes the token details page use the same asset metadata and icon
as when opened from the main Tokens page.

## **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: Show Arc USDC balance and details from native asset in
swap asset picker

## **Related issues**

Fixes:

## **Manual testing steps**

1. Build and run the extension.
2. Use an account with an Arc USDC balance.
3. Open Swap.
4. Open the source asset picker.
5. Select or filter to Arc.
6. Verify the USDC row shows the user’s USDC balance instead of an empty
line.
7. Verify other Arc tokens with balances, such as EURC, still show their
balances.
8. Click the `i` icon on the Arc USDC row.
9. Verify the token details page opens and the USDC icon is displayed
correctly.
10. From the main Tokens page, open Arc USDC details and verify the same
icon/details are shown.

## **Screenshots/Recordings**

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

### **Before**

<!-- [screenshots/recordings] -->
<img width="350" height="377" alt="46840 Before_1"
src="https://github.com/user-attachments/assets/4f0c15e5-1fa3-476d-9366-79ff82cc0ef8"
/>
<img width="350" height="377" alt="46840 Before_2"
src="https://github.com/user-attachments/assets/1a38c5a5-d656-4507-b2e5-2addc5b0e355"
/>

### **After**

<!-- [screenshots/recordings] -->
<img width="350" height="377" alt="46840 After_1"
src="https://github.com/user-attachments/assets/c17f8e2d-f59e-4faf-9295-ac17c89d3efc"
/>
<img width="350" height="377" alt="46840 After_2"
src="https://github.com/user-attachments/assets/3945d132-c7a7-4520-a1cf-b38ffab6bdf0"
/>

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes swap balance resolution and asset routing for Arc USDC;
incorrect aliasing could show wrong balances or open the wrong details
page, but scope is limited to Arc bridge/swap flows with new tests.
> 
> **Overview**
> Fixes Swap/Bridge handling when Arc **USDC** is stored as the native
`slip44` balance but swaps must use the validated **ERC-20 wrapper**
CAIP ID.
> 
> New Arc helpers map bridge lookup IDs to wallet balances
(`getArcBridgeAssetIdAliases`) and rewrite asset-details routes from
ERC-20 USDC to the native asset ID (`getArcAssetDetailsRouteAssetId`).
Bridge asset selectors now build balances from **hidden** assets
(including native Arc) while the picker list still filters them out;
`getBridgeAssetsByAssetId` aliases native USDC onto the ERC-20 entry
with **6-decimal** bridge metadata so the visible USDC row shows the
correct balance.
> 
> `navigateToAssetPage` uses the native route when opening details from
the picker info icon, matching the main Tokens page icon/metadata. Tests
cover selector aliasing and navigation.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
4bbaaa1. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Gabriele Del Monte <gabrieledm@users.noreply.github.com>
## **Description**

Part 7 of the 18-part assets-unification stack.

test(assets): cover unified compatibility selectors. This focused slice
keeps the review below the 1,000 changed-line limit while preserving the
final behavior of the original PR.

## **Changelog**

CHANGELOG entry: null

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

Fixes:
-->

## **Manual testing steps**

1. Build and load the extension.
2. Unlock or onboard a wallet.
3. Verify home balances and token lists render.
4. Open send and bridge token selectors and verify assets are available.

<!--
## **Screenshots/Recordings**

### **Before**

### **After**
-->

## **Pre-merge author checklist**

- [x] I have followed MetaMask coding standards.
- [x] I have completed the PR template.
- [x] I have included tests where applicable.

## **Pre-merge reviewer checklist**

- [ ] I have manually tested the PR.
- [ ] I confirm the acceptance criteria and testing evidence.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Test-only changes to assets-migration selector coverage; no production
code modified.
> 
> **Overview**
> Refactors **`assets-migration.test.ts`** so the first batch of
unified-state compatibility selectors
(`getAccountTrackerControllerAccountsByChainId`, token
list/ignore/balance selectors, and
`getMultiChainAssetsControllerAccountsAssets`) are tested only on the
**enabled** unified-assets path.
> 
> **Removes** the nested `when assets unify state feature is disabled`
suites that asserted legacy state passthrough for those selectors.
**Flattens** describe blocks (happy path at top level, `edge cases`
renamed) and **standardizes** fixtures with shared `enabledFlags`
instead of inline `remoteFeatureFlags`.
> 
> **Tightens** `makeMockPrice` with a `FungibleAssetPrice`-typed helper
(including `usdPrice` and optional `null` overrides for non-finite
market data). Production selector code is unchanged; this slice is
test-only.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
ef46843. 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**

E2E boots with the synced production remote flags. `stellarAccounts` is
on for app 13.53.0, so the default wallet now has a Stellar account.
Startup calls a new host, rewards stores that account, and two specs
still expected the old account count and connect grants.

**Root cause:**

- E2E boots with the synced production remote flags.
- stellarAccounts is now enabled for app 13.53.0 (minimumVersion
13.50.0).
- Wallet init turns on the Stellar provider and creates a Stellar pubnet
account.
- That boot calls stellar-mainnet.infura.io, which was missing from the
privacy snapshot.
- Rewards stores that account, and the default fixture schema did not
contain it.
- DappViewed counts internal accounts, so number_of_accounts is 5. The
spec still expected 4.
- Default connect grants every non-test network that has an account, so
the caveat now includes stellar:pubnet. The spec still expected only
EVM, Solana, Bitcoin, and Tron.

**Solution:**

- Add stellar-mainnet.infura.io to privacy-snapshot.json so the startup
request is allowed.
- Add the Stellar rewards account to default-fixture.json and ignore its
lastFreshOptInStatusCheck timestamp so the fixture matches the new
account.
- Set METAMASK_IDENTITIES to 5 in dapp-viewed.spec.ts so DappViewed
expects the Stellar account.
- Add stellar:pubnet to DEFAULT_PERMITTED_CAIP_CHAIN_IDS so the connect
tests expect the Stellar grant.

## **Changelog**

CHANGELOG entry: null

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

Fixes:
-->

## **Manual testing steps**

1. Start a test build with `yarn start:test` if one is not already
running. These specs are not Flask tests.
2. Run the dapp viewed metrics spec:

```bash
SELENIUM_BROWSER=chrome yarn test:e2e:single test/e2e/tests/metrics/dapp-viewed.spec.ts --debug --leave-running
```

3. Run the multiple provider connections spec:

```bash
SELENIUM_BROWSER=chrome yarn test:e2e:single test/e2e/tests/connections/multiple-provider-connections.spec.ts --debug --leave-running
```

## **Screenshots/Recordings**

### **Before**

No product UI change. This PR only updates E2E snapshots, fixtures, and
assertions.

### **After**

No product UI change. This PR only updates E2E snapshots, fixtures, and
assertions.

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

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Harry Le <43307514+LeVinhGithub@users.noreply.github.com>
Co-authored-by: LeVinhGithub <levinh.hcmut@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…6809)

## **Description**

The gasless EIP-7702 relay flow signs delegations to `ANY_BENEFICIARY`,
so there is no restriction on which address can submit the
`redeemDelegations` call.

- The 7702 publish hook now adds a `RedeemerEnforcer` caveat, which
restricts redemption to the Sentinel relay signers (`cubistSigners` from
the Sentinel `/networks` API), plus the delegatee if one is set.
- If a chain has no relay signers, the hook throws before signing rather
than falling back to an unrestricted delegation.
- `convertTransactionToRedeemDelegations` accepts an optional
`redeemers` list. Callers that don't pass it, such as enforced
simulations and MetaMask Pay, are unchanged.

Gas fee token estimates need to include the enforcer to match. That
comes from MetaMask/core#10615, which needs to
be released and bumped here.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

Depends on: MetaMask/core#10615

## **Manual testing steps**

1. On a relay-enabled chain, submit a transaction paying gas with a gas
fee token, or a sponsored transaction.
2. Confirm the relay submits and confirms it.
3. Confirm the `redeemDelegations` calldata sent to the relay includes
the `RedeemerEnforcer` caveat, with the chain's relay signers as terms.

## **Screenshots/Recordings**

### **Before**

### **After**

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **High Risk**
> Changes who may redeem signed delegations in the gasless relay path;
misconfigured signers or caveat terms could block legitimate relays or
weaken redemption restrictions.
> 
> **Overview**
> Gasless EIP-7702 relay delegations previously allowed **any** address
to call `redeemDelegations` because delegations target
`ANY_BENEFICIARY`. This change **locks redemption** to Sentinel relay
signers.
> 
> The **7702 publish hook** loads `cubistSigners` from Sentinel’s
`/networks` API via new **`getSentinelSigners`**, and **aborts before
signing** if the list is empty so the wallet never publishes an
unrestricted delegation. It passes those addresses into
**`convertTransactionToRedeemDelegations`** as optional **`redeemers`**,
which **appends a `RedeemerEnforcer` caveat** (using
`createRedeemerTerms`) on top of default or caller-supplied caveats; the
optional **delegatee** is included and duplicates are deduped. Callers
that omit **`redeemers`** behave as before.
> 
> E2E mocks now return **`cubistSigners`** for relay tests, and
**`@metamask/transaction-controller`** is bumped to **72.1.0** (aligned
with gas-fee estimate enforcer support in core).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
bba7d7c. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Ports
[metamask-mobile#36412](MetaMask/metamask-mobile#36412):
lets Money Account deposit **Max** be quoted atomically (`EXACT_OUTPUT`)
instead of always forcing non-atomic.

`atomic` is left unset — so Core applies its atomic default — only when
**both** hold:

1. `confirmations_pay_extended.payStrategies.relay.atomicMaxEnabled` is
on for the transaction type, and
2. the selected pay token → destination route matches
`confirmations_relay_fixed_spread`.

Otherwise Max keeps setting `atomic: false`, preserving today's
behaviour. The route match only *predicts* the subsidy; Core verifies
the returned quote and re-quotes non-atomically if it isn't subsidized.

Also: the hint is refreshed if the flag changes while Max is armed, and
clearing a payment override no longer overwrites it.

> [!IMPORTANT]
> **Depends on a separate dependency PR.** The Core implementation ships
in `@metamask/transaction-pay-controller@29.1.0`; this branch is pinned
to `27.1.1`, so the new code is inert until that lands. Merge/rebase
this **after** the package bump.
>
> That PR must also rename the delegated messenger action
`RampsController:getQuotes` → `getQuoteWithFees` (required by TPC 29)
and bump `@metamask/ramps-controller` to `^23`, which is the first
version exporting the matching action type.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

- https://consensyssoftware.atlassian.net/browse/CONF-1949
- Core: MetaMask/core#10224

## **Configuration**

```json
{
  "payStrategies": {
    "relay": {
      "atomicMaxEnabled": {
        "default": false,
        "transactionTypes": { "moneyAccountDeposit": true }
      }
    }
  }
}
```

Merge into the existing `confirmations_pay_extended` value.
`transactionTypes` is a type→boolean **object, not an array** — an array
silently leaves the gate off.

## **Manual testing steps**

> Requires the dependency PR (see above).

1. Apply the flag config, and ensure `confirmations_relay_fixed_spread`
has a matching route for your pay token (e.g. USDC → mUSD).
2. Money Account → Add funds → pick that pay token → press **Max**.
3. Verify the quote is atomic `EXACT_OUTPUT` (single quote, vault calls
embedded).
4. Turn the gate off, reload, press **Max** → verify it falls back to
non-atomic `EXACT_INPUT`.
5. Press **Max**, then switch to a pay token **not** in the fixed-spread
config → verify it stays non-atomic.
6. With Max armed, toggle payment method to Money Account and back →
verify an atomic-eligible Max is not forced back to non-atomic.
7. Press **Max**, then pick 50% or type an amount → verify the Max
override is cleared.

<!--
## **Screenshots/Recordings**

### **Before**

### **After**
-->

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes Pay quoting hints and deposit Max behavior on money-account
flows; defaults stay non-atomic when flags or routes do not match, but
incorrect gating could affect quote mode and amounts.
> 
> **Overview**
> Enables **atomic Max** quoting for Money Account deposits when remote
config allows it, instead of always forcing `atomic: false` on Max.
> 
> The confirmation amount hook now derives **`isAtomicMaxAllowed`** from
`confirmations_pay_extended.payStrategies.relay.atomicMaxEnabled` (per
transaction type, including nested batches) **and** a fixed-spread route
match via `confirmations_relay_fixed_spread`. That flag is passed into
`setIsMaxAmount`; the background init leaves **`config.atomic` unset**
(Core’s atomic default) only when atomic Max is allowed, otherwise it
still sets `atomic: false`. A new **`setTransactionPayAtomic`** path
refreshes the hint when the gate changes while Max is already armed, and
**clearing a payment override** no longer overwrites an armed deposit
Max’s atomic hint.
> 
> **`getTokenAddress`** now resolves the destination from
**`requiredAssets`** for vault-targeted deposit batches so route
matching uses mUSD, not the parent `to`.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
00bb6c5. 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

Onboarding journey Sentry p90s currently include user think-time, such
as entering an SRP and choosing a password. This makes the metrics
difficult to use for performance monitoring and creates misleading
outliers in the State of Quality report.

This change adds separate machine-time instrumentation while preserving
the existing wall-clock journey traces.

### Changes

- Added machine-time child traces for:
  - Existing SRP import
  - New SRP wallet creation
  - New social wallet creation
- Added `onboarding.machine.ms` to the overall onboarding journey span.
- Excluded failed spans and nested backup work from the aggregate to
avoid double counting.
- Preserved trace parent context across buffered Sentry traces.
- Added `account_type` attributes to onboarding traces.
- Added `perf_fix=trace-registry-v1` as a release-boundary marker for
before/after comparisons.
- Added lifecycle and aggregation tests.

### Metric semantics

- Existing wall-clock journey traces continue measuring total user
journey time, including think-time.
- Machine-time child spans measure only application work:
  - SRP import: `importWithRecoveryPhrase` duration.
  - Wallet creation: `createNewAccount` duration.
- `onboarding.machine.ms` contains the sum of successful machine-time
child spans for the journey.

## Changelog

CHANGELOG entry: null

## Related issues

Fixes:

## Manual testing steps

1. Load the extension and start a fresh onboarding flow.
2. Complete an existing SRP import.
3. Repeat with new SRP wallet creation and social wallet creation.
4. Confirm all onboarding flows complete normally without navigation
regressions.
5. Verify that no user-facing UI behavior has changed.

## Screenshots/Recordings

Not applicable. This is an observability-only change with no user-facing
UI changes.

## Testing

- `yarn lint:tsc`
- `yarn lint:changed:fix`
- `yarn test:unit shared/lib/trace.test.ts
ui/pages/onboarding-flow/create-password/create-password.test.tsx
--runInBand --watchman=false`
- 64 focused tests passed.

Live Sentry verification and State of Quality/watchlist query alignment
will be performed separately.

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

1. Go to this page...
2.
3.

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

- [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**
> Observability-only changes to onboarding tracing and metrics
buffering; wallet flows and navigation logic are largely unchanged aside
from trace wrappers around existing async calls.
> 
> **Overview**
> Adds **onboarding machine-time** Sentry instrumentation so performance
metrics can separate application work from user think-time, while
keeping existing wall-clock journey traces.
> 
> The trace layer now aggregates successful “machine” child spans into
`onboarding.machine.ms` on `OnboardingJourneyOverall` (excluding
failures, password/OAuth interaction spans, and double-counted nested
backup work), and exposes `getTraceContext` / `annotateTrace` plus
mobile-aligned trace names for SRP create/import duration. **Create
password** starts and ends buffered child traces around
`createNewAccount` and `importWithRecoveryPhrase` with `account_type`
and journey parent context; **welcome** and **onboarding flow** attach
`account_type` / `perf_fix: trace-registry-v1` on related spans.
> 
> **SentryTracingService** no longer drops serialized `{ _name, _id }`
parent context when buffering pre–metrics-opt-in traces, so nested spans
still link after flush. Unit tests cover aggregation rules, buffering,
and UI trace wiring.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
53986a9. 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**

This PR recreates the stale hid object that isn't removed when the
webhid permission has been removed.

<!--
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: fix ledger connection when permission has been revoked.

## **Related issues**

Fixes:

## **Manual testing steps**

1. Connect with a ledger account
2. Go to site settings and block the webhid connection
3. See that connection modal popup when trying to use the device
4. Reenable webhid
5. See the connection is working again. 

## **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**
> Changes core offscreen Ledger connection lifecycle (caching, teardown
races, WebHID permission edge cases); mistakes could break reconnect or
leak listeners, but behavior is heavily covered by new tests.
> 
> **Overview**
> Fixes Ledger DMK offscreen handling when **WebHID permission is
revoked** (no native disconnect): cached bridges are
**liveness-checked** against a snapshot of permitted `HIDDevice`
objects, torn down synchronously when stale, and rebuilt without
blocking on a hung `bridge.destroy()`.
> 
> **Transport teardown** is new: each bridge’s WebHID transport is
captured at creation and **`destroy()`** is invoked on disconnect,
permission loss, `forceReset`, handler destroy, and failed/orphaned
construction—so `navigator.hid` listeners do not leak in the long-lived
offscreen document. Bridge construction state (transport + device
snapshot) is only published after the generation check to avoid races
with discarded in-flight builds.
> 
> **RPC error messaging**: hardware-wallet `getErrorMessage` now uses
`extractMessageFromUnknownError`, so plain-object failures are
**JSON-stringified** instead of `"[object Object]"`. Tests cover
stale-bridge, permission revoke/re-grant, transport lifecycle, and the
updated discovery error message.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
7877570. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## **Description**

The remote flag `extension-ux-default-address-versioned`
(`extensionUxDefaultAddressVersioned`) is already enabled in production.
This change removes the client check and keeps the enabled behavior
permanently.

Default address stays available in settings, the account list, the QR
sync account list, and the homepage header. The **Show default address**
preference still controls whether the address is displayed.

The registry entry is marked deprecated, with the production default
unchanged, so the daily flag sync does not re-add it as an active flag
before it is retired server-side.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

1. Run the extension and unlock or create a wallet.
2. On the homepage, confirm the default address is shown under the
account name in the header.
3. Open the address popover from that header row and confirm the **Show
default address** section is present.
4. Open Settings, then General (Preferences and display).
5. Confirm the **Show default address** toggle and network dropdown are
visible.
6. Turn **Show default address** off.
7. Return to the homepage and confirm the default address is hidden in
the header.
8. Open the account list and confirm account rows no longer show the
default address.
9. Turn **Show default address** back on and confirm the address returns
in the header and account list.

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

<div><a
href="https://cursor.com/agents/bc-e450b381-60f1-42c5-9e00-eabf31013f7f?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-e450b381-60f1-42c5-9e00-eabf31013f7f&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Amélie <ameliejyc@users.noreply.github.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<details>
<summary>Tron release changelog v4.0.0</summary>

### Added

- Add `signProofOfOwnershipBatch` for signing multiple
proof-of-ownership messages in one request.
([#265](MetaMask/internal-snaps#265))
- Emit `Transaction Added`, `Transaction Approved`, and `Transaction
Rejected` for `signTransaction` confirmations
([#333](MetaMask/internal-snaps#333))
- Only dApp-initiated transaction confirmations were affected; the
unified send flow already emitted these events.
- Report account synchronization failures to Sentry with the failing
account IDs and their failure reasons
([#374](MetaMask/internal-snaps#374))

### Changed

- **BREAKING** Bump `@metamask/keyring-api` from `^23.7.0` to `^24.1.0`
([#214](MetaMask/internal-snaps#214))
- **BREAKING** Bump `@metamask/keyring-snap-sdk` from `^9.2.1` to
`^10.0.0` ([#214](MetaMask/internal-snaps#214))
- **BREAKING** Bump `@metamask/snaps-sdk` from `^11.2.0` to `^12.0.1`
([#214](MetaMask/internal-snaps#214))

### Removed

- **BREAKING** Remove the deprecated `asset` cluster of handlers:
`onAssetHistoricalPrice`, `onAssetsConversion`, `onAssetsLookup` and
`onAssetsMarketData`
([#263](MetaMask/internal-snaps#263))

### Fixed

- Emit `Transaction Submitted` from the Wallet Standard
`signAndSendTransaction` path so its transactions no longer reach
`Transaction Finalized` without a matching submit event
([#343](MetaMask/internal-snaps#343))
- Tolerate unknown fields in the Token API metadata response so that new
fields added by the API no longer fail validation and fall back to
default token metadata
([#320](MetaMask/internal-snaps#320))

</details>
<details>
<summary>Solana release changelog v7.0.0</summary>

### Added

- Add `signProofOfOwnershipBatch` for signing multiple
proof-of-ownership messages in one request.
([#256](MetaMask/internal-snaps#256))
- Add back the `endowment:assets` permission for the Solana scopes to
the snap manifest, with no-op `onAssetsLookup`, `onAssetsConversion`,
`onAssetHistoricalPrice`, and `onAssetsMarketData` entry points required
to keep the permission
([#274](MetaMask/internal-snaps#274))
- Report account synchronization failures to Sentry with the failing
account IDs and their failure reasons
([#376](MetaMask/internal-snaps#376))

### Changed

- **BREAKING:** Bump `@solana/kit` from `^6.9.0` to `^8.3.0` and the
`@solana-program/*` clients (`compute-budget` `^0.18.1`, `system`
`^0.14.1`, `token` `^0.16.1`, `token-2022` `^0.17.0`) to their Kit
8-compatible versions.
([#303](MetaMask/internal-snaps#303))
- **BREAKING:** Update the Solana Name Service integration to SNS SDK v1
and the Kit 6.9-compatible Solana program clients
([#271](MetaMask/internal-snaps#271))
- **BREAKING** Bump `@metamask/keyring-api` from `^23.7.0` to `^24.1.0`
([#214](MetaMask/internal-snaps#214))
- **BREAKING** Bump `@metamask/keyring-snap-sdk` from `^9.2.1` to
`^10.0.0` ([#214](MetaMask/internal-snaps#214))
- **BREAKING** Bump `@metamask/snaps-sdk` from `^11.2.0` to `^12.0.1`
([#214](MetaMask/internal-snaps#214))
- Reduce `snap_getBip32Entropy` calls in `createAccounts` from two to
one for `bip44:discover` by deriving the activity-check address locally
from the already-fetched coin-type node, and parallelize the entropy
fetch with the existing-accounts state read for all creation paths
([#304](MetaMask/internal-snaps#304))
- Coalesce concurrent `AccountsSynchronizer.synchronize` calls for the
same account set so duplicate in-flight syncs (e.g. simultaneous
connection-recovery events across mainnet and devnet) share one run
instead of fanning out redundant asset and transaction fetches
([#304](MetaMask/internal-snaps#304))
- Migrate `trackError` and `withCatchAndThrowSnapError` to
`@metamask/snap-networks-utils` `createSnapErrorHandling`, and add
`getSnapProvider` for Snap RPC access
- Extract Snap-owned assets domain logic into `SnapAssetsAdapter`;
`AssetsService` is a thin facade that delegates metadata, market data,
fetch, persist, and account asset reads through the adapter (no Core
routing yet).
([#121](MetaMask/internal-snaps#121))
- Align `AssetsService` read API with `snap-networks-utils` /
AssetsController shapes by adding `getAccountAssetByID`,
`getAccountAssetsByIDs`, `getAccountAssetsByScope`, and
`getAccountAssets`, and routing Keyring and Send through them (still
Snap-owned storage).
([#120](MetaMask/internal-snaps#120))
- Bump `@metamask/utils` from `^11.9.0` to `^11.11.9`
([#161](MetaMask/internal-snaps#161))

### Removed

- **BREAKING** Remove the `onAssetsLookup`, `onAssetsConversion`,
`onAssetHistoricalPrice`, and `onAssetsMarketData` asset handler entry
points, along with the now-unused handler modules and the
`endowment:assets` permission
([#261](MetaMask/internal-snaps#261))
- **BREAKING** Remove `AssetsService.fetchAssetsMarketData` and
`SnapAssetsAdapter.fetchAssetsMarketData`, the `TokenPricesService`
class, and `PriceApiClient.getHistoricalPrices`, all of which were only
used by the removed asset handlers
([#261](MetaMask/internal-snaps#261))
- Remove the now-unused `PriceApiClient.getFiatExchangeRates` method and
related `ExchangeRate` type, the unused `tokenPrices` unencrypted state
field, the unused `fiatExchangeRates` and `historicalPrices` price API
cache TTL options, and unused price API test mocks
([#261](MetaMask/internal-snaps#261))

### Fixed

- **BREAKING:** Preserve dapp-origin `signTransaction` and
`signAndSendTransaction` payloads by signing the decoded transaction
directly ([#156](MetaMask/internal-snaps#156))
- Prevent signing dapp transactions with expired blockhashes, and
refresh the blockhash for MetaMask-originated transactions before
signing. ([#183](MetaMask/internal-snaps#183))
- Tolerate unknown fields in the Price API spot price and Token API
metadata responses so that new fields
added by the API no longer fail validation
([#321](MetaMask/internal-snaps#321))
- Emit an `AccountTransactionsUpdated` keyring event with a pending
`unconfirmed` transaction immediately after broadcasting.


</details>
<details>
<summary>Bitcoin release changelog v3.1.0</summary>

### Added

- Add `signProofOfOwnershipBatch` for signing multiple
proof-of-ownership messages in one request.
([#266](MetaMask/internal-snaps#266))
- Emit `Transaction Added`, `Transaction Approved`, and `Transaction
Rejected` tracking events from Bitcoin transaction confirmations
([#328](MetaMask/internal-snaps#328),
[#329](MetaMask/internal-snaps#329))
- Report account synchronization failures to Sentry with the failing
account IDs and their failure reasons
([#375](MetaMask/internal-snaps#375))

### Fixed

- Populate the `from` address of receive transactions by resolving the
addresses that funded them through the chain indexer. Bitcoin inputs
only reference a previous outpoint, so the sender was previously left
empty. ([#372](MetaMask/internal-snaps#372))

</details>

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

n/a

## **Manual testing steps**

n/a

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

- [ ] 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**
> Major Solana and Tron snap upgrades can change signing, sync, and
keyring behavior in production multichain flows; extension code changes
are limited to dependency versions and e2e mocks.
> 
> **Overview**
> Bumps bundled multichain wallet Snaps: **Solana** `5.0.1` → `7.0.0`,
**Tron** `3.2.0` → `4.0.0`, and **Bitcoin** `3.0.0` → `3.1.0`, with
matching `yarn.lock` updates.
> 
> E2E tests are adjusted for the new Solana snap behavior: the
multichain `wallet_invokeMethod` **signAndSendTransaction** assertion
uses an updated expected transaction **signature**, and the SPL token
send success mocks swap **`mockGetTokenAccountBalance`** for
**`mockGetSuccessSignaturesForAddress`** after broadcast so
activity/history RPC expectations align with v7.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
c3efb9d. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Part 8 of the 18-part assets-unification stack.

test(assets): cover unified multichain and currency selectors. This
focused slice keeps the review below the 1,000 changed-line limit while
preserving the final behavior of the original PR.

## **Changelog**

CHANGELOG entry: null

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

Fixes:
-->

## **Manual testing steps**

1. Build and load the extension.
2. Unlock or onboard a wallet.
3. Verify home balances and token lists render.
4. Open send and bridge token selectors and verify assets are available.

<!--
## **Screenshots/Recordings**

### **Before**

### **After**
-->

## **Pre-merge author checklist**

- [x] I have followed MetaMask coding standards.
- [x] I have completed the PR template.
- [x] I have included tests where applicable.

## **Pre-merge reviewer checklist**

- [ ] I have manually tested the PR.
- [ ] I confirm the acceptance criteria and testing evidence.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Test-only refactor in assets-migration.test.ts; no production selector
logic changes in this diff.
> 
> **Overview**
> Refactors **`assets-migration.test.ts`** so multichain and currency
migration selectors are exercised only on the **assets-unify enabled**
path, matching the stack’s expected runtime behavior.
> 
> For `getMultiChainAssetsControllerAssetsMetadata`,
`getMultiChainAssetsControllerAllIgnoredAssets`,
`getMultiChainBalancesControllerBalances`,
`getCurrencyRateControllerCurrentCurrency`,
`getCurrencyRateControllerCurrencyRates`, and
`getTokenRatesControllerMarketData`, it **drops** nested “feature
disabled / legacy passthrough” suites and **flattens** the enabled
cases: shared `enabledFlags` fixtures, top-level happy-path `it`s, and
`edge cases` blocks without the “when enabled” wrapper. Assertions for
unified derivation (non-EVM filtering, Tempo USD rates, native-currency
market data) are unchanged.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f5fe123. 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>
…46859)

## **Description**

The add-network form had a separate **Add from Chainlist** button that
opened another screen.
[CEUX-1312](https://consensyssoftware.atlassian.net/browse/CEUX-1312)
asks for Chainlist suggestions on the form itself.

Clicking or focusing the **Network name** field now opens the Chainlist
list under that field. Typing filters by network name or chain ID.
Choosing a suggestion prefills the form (name, chain ID, symbol, RPC
URL, and block explorer) and uses the existing add flow. An
already-added chain still opens the edit screen. Typing a name without
picking a suggestion leaves the other fields unchanged. The **Add from
Chainlist** button is removed.

The old `?view=add-from-chainlist` screen is still reachable by URL.
Chain ID does not open the same suggestions yet.

## **Changelog**

CHANGELOG entry: Added Chainlist suggestions to the network name field
when adding a network

## **Related issues**

Related:
[CEUX-1312](https://consensyssoftware.atlassian.net/browse/CEUX-1312)

## **Manual testing steps**



1. Run the extension and set the flag (`extension-ux-chainlist-v-2`) to
true
2. Open Settings → Networks → Add a custom network.
3. Confirm there is no **Add from Chainlist** button.
4. Click **Network name**. Confirm the Chainlist banner and network list
open under the field.
5. Type part of a network name or a chain ID and confirm the list
filters. An empty field shows the full list.
6. Select a network that is not already added. Confirm name, chain ID,
symbol, RPC URL, and block explorer are filled, then save.
7. Select a network that is already added. Confirm the edit-network
screen opens for that chain.
8. Type a custom name, click outside the list, and fill the other fields
by hand. Confirm they are not overwritten.
9. Edit an existing network. Confirm the suggestions do not open and
Chain ID stays disabled.


## **Screenshots/Recordings**

### **Before**
NA

### **After**





https://github.com/user-attachments/assets/32e0584e-afa7-4fe6-8acc-3061134dfc24





## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

- [ ] 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)

[CEUX-1312]:
https://consensyssoftware.atlassian.net/browse/CEUX-1312?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
[CEUX-1312]:
https://consensyssoftware.atlassian.net/browse/CEUX-1312?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
…46777)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Bump @metamask/delegation-deployments from ^2.0.0 to ^2.1.0, bringing
Ark chain deployments.

## **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: @metamask/delegation-deployments from ^2.0.0 to ^2.1.0

## **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**
> Lockfile-only bump of deployment metadata; no local logic changes,
though wrong addresses on a new chain would affect delegation flows on
Ark.
> 
> **Overview**
> Updates **`@metamask/delegation-deployments`** from **^2.0.0** to
**^2.1.0** in `package.json`, with the matching **`yarn.lock`**
resolution for **2.1.0**.
> 
> Per the PR description, **2.1.0** adds **Ark chain** delegator
deployment metadata consumed transitively by delegation-related
controllers (e.g. `@metamask/delegation-controller`, gator permissions,
money-account upgrade). There are **no extension source changes** in
this diff—only the dependency version.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
3e19080. 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**

Stabilize the phishing detection E2E that times out on Firefox while the
warning is already showing inside an iframe.

**Flake type:** Race Conditions with Windows

**Root cause:**

- The test opens a mock page that puts a blocked site inside an iframe.
- Early blocking is turned off, so the iframe loads the blocked site
first.
- A content script then moves that frame to the MetaMask phishing
warning.
- The helper finds the first iframe and switches into it once, about
half a second after the page opens.
- The frame is often still the blocked site at that moment.
- It then waits for the heading "This website might be harmful".
- On Firefox, that one-time switch stays on a frame that never gets the
heading, even after the warning is painted.
- The failed page already shows the warning inside the iframe while the
test times out.
- The helper only goes back to the top page after that wait, which is
too late.

**Solution:**

- Return to the top page and enter the iframe again until the warning
heading is visible, so the click runs in the frame that actually shows
the warning.
- Click "Open this warning in a new tab" once after that wait, so an
early switch is not treated as a click to retry.


Slack:
https://consensys.slack.com/archives/CTQAGKY5V/p1790848005313319?thread_ts=1790843210.528129&cid=CTQAGKY5V

## **Changelog**

CHANGELOG entry: null

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

Fixes:
-->

## **Manual testing steps**

1. Start a test build with `yarn start:test`. This spec is not a Flask
test.
2. Remove `it.only` from the failing test before committing or opening a
PR.
3. Run:

```bash
SELENIUM_BROWSER=chrome yarn test:e2e:single test/e2e/tests/phishing-controller/phishing-detection.spec.ts --debug --leave-running
```

This race shows up on Firefox. Chrome usually passes. To hit the same
failure, use a Firefox test build (`yarn start:test:mv2`) and set
`SELENIUM_BROWSER=firefox` on that command.

## **Screenshots/Recordings**
<img width="1366" height="682" alt="image"
src="https://github.com/user-attachments/assets/bf135dc9-bafd-40e2-aa66-ef8fe3b741ac"
/>

### **Before**

CI failure screenshot: a mock page with "Hello" at the top left and a
large black iframe that already shows the MetaMask phishing warning
("This website might be harmful", warning icon, and the link "Open this
warning in a new tab"). The test still timed out looking for that
heading inside the iframe.

A second screenshot is the MetaMask home window left open after login
(Account 1, 25 ETH, Network: Localhost 8545). The test never returned to
that window because the iframe wait failed first.

### **After**

No product UI change. The helper returns to the top page, re-enters the
iframe until the warning heading is visible, then clicks "Open this
warning in a new tab" once.

## **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**
> Test-only page-object change; no product or runtime behavior.
> 
> **Overview**
> Fixes a **Firefox flake** in the phishing-detection E2E where the
helper switched into an iframe once while it still showed the blocked
site, then timed out waiting for the warning heading even after the
interstitial appeared.
> 
> **`clickOpenWarningInNewTabLinkOnIframe`** now **polls** (up to 10s):
reset to default content, re-find the iframe, switch in, and confirm
**"This website might be harmful"** is visible before clicking **"Open
this warning in a new tab"** once. Drops the unused **`WebElement`**
import and the old one-shot frame switch plus **`checkPageIsLoaded`**
path.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f77e4a4. 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>
@sleepytanya
sleepytanya requested review from a team and itsyoboieltr as code owners October 19, 2026 18:08
sleepytanya
sleepytanya previously approved these changes Oct 19, 2026

@cursor cursor Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Modern web & extension review (actionable)

Reviewed client-facing changes under ui/ / shared/ and extension work under app/ against modern-web-guidance and chrome-extensions patterns.

Cashtag (X) widget — browser support gaps

  1. Interest Invokers have no fallback. bindWidgetTriggers opens the widget only via interestfor on cashtag anchors. Elsewhere in the extension (e.g. ui/pages/ramps/payment-method/components/ramps-quote-display.tsx) we feature-detect interestFor and ship a pointer/focus fallback. Without the same pattern, the widget will not open on browsers that lack Interest Invokers (including Firefox and older Chromium builds).

  2. Invoker Commands are used without a polyfill or fallback. OverflowMenu and DisableConfirmDialog depend on command / commandfor (toggle-popover, show-modal, close). modern-web-guidance calls for feature detection and the invokers polyfill when native support is missing; there is no polyfill in this repo today, so disable/menu flows can be inert outside supporting browsers.

  3. Content script DOM work should be batched. injectPills / bindWidgetTriggers paint cashtags synchronously inside a MutationObserver loop. chrome-extensions guidance recommends batching DOM updates with requestAnimationFrame (and yielding on long feeds) to avoid main-thread jank on X timelines.

Accessibility

  1. PriceChart is a canvas with no accessible name or text alternative. Add at least aria-label / role="img" with a concise price summary, or expose a screen-reader-friendly value table per accessibility guidance for charts.

Minor

  1. OverflowMenu accepts ariaLabel / testId but always hard-codes the trigger label — wire the props through or drop them from the public API.

Other UI changes in this release (tabs keyboard handling, labeled RPC form fields, native <dialog> for disable confirm) align well with modern patterns where supported.

Open in Web View Automation 

Sent by Cursor Automation: Modern web guidance

if (mounted.has(element)) {
return;
}
element.setAttribute('interestfor', popoverId);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Widget open is tied exclusively to interestfor. Consider mirroring interestInvokerSupport + fallback handlers from ramps-quote-display.tsx (click/focus + popover show/hide) so cashtags work when Interest Invokers are unavailable.

ariaLabel="More options"
style={{ anchorName: '--menu-trigger' } as React.CSSProperties}
// @ts-expect-error need to update react types
command="toggle-popover"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invoker Commands (toggle-popover / item show-modal) need a feature-detect + invokers-polyfill (or explicit click handlers) per modern-web-guidance — otherwise this menu is a no-op on unsupported browsers, including inside the X iframe widget.

);
}

return <div ref={containerRef} className="h-[170px] w-full" />;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chart container is a bare <div> around a canvas with no accessible name. Please add an aria-label / role="img" with a short price summary, or an sr-only text alternative for the series.


scan(document);

const observer = new MutationObserver((mutations) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This observer can call paint/replaceChildren for many nodes in one turn. Batch scans/paints with requestAnimationFrame (and yield between batches on large feeds) to match content-script performance guidance and reduce INP risk on X.

@metamask-ci

metamask-ci Bot commented Oct 19, 2026

Copy link
Copy Markdown
Contributor
Builds ready [a13345c]
⚡ Performance Benchmarks (Total: 🟢 8 pass · 🟡 2 warn · 🔴 3 fail)

Baseline (latest main): 171ed20 | Date: 7/28/2026 | Pipeline: 39301060174 | Baseline logs

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

Regressions (🔴 3 failures)

Interaction Benchmarks · Samples: 5 🔴 2
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🔴 [CI log]
🔴 load_new_account
🔴 [CI log]
🔴 load_new_account
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/load_new_account: +417%
  • ↑ loadNewAccount/total: +417%
  • ↓ loadNewAccount/inp: -24%
  • ↑ confirmTx/longTaskTotalDuration: +40%
  • ↑ confirmTx/longTaskMaxDuration: +67%
  • ↑ confirmTx/tbt: +70%
  • ↓ confirmTx/inp: -24%
  • ↑ bridgeUserActions/bridge_load_page: +78%
  • ↑ bridgeUserActions/bridge_load_asset_picker: +72%
  • ↑ bridgeUserActions/longTaskCount: +67%
  • ↑ bridgeUserActions/longTaskTotalDuration: +96%
  • ↑ bridgeUserActions/longTaskMaxDuration: +33%
  • ↑ bridgeUserActions/tbt: +161%
  • ↑ bridgeUserActions/total: +12%
  • ↑ loadNewAccount/load_new_account: +417%
  • ↑ loadNewAccount/total: +417%
  • ↓ loadNewAccount/inp: -39%
  • ↓ loadNewAccount/fcp: -69%
  • ↑ loadNewAccount/lcp: +1258%
  • ↓ confirmTx/longTaskCount: -100%
  • ↓ confirmTx/longTaskTotalDuration: -100%
  • ↓ confirmTx/longTaskMaxDuration: -100%
  • ↓ confirmTx/tbt: -100%
  • ↑ confirmTx/inp: +112%
  • ↓ confirmTx/fcp: -77%
  • ↑ confirmTx/lcp: +900%
  • ↑ bridgeUserActions/bridge_load_page: +93%
  • ↑ bridgeUserActions/bridge_load_asset_picker: +65%
  • ↓ bridgeUserActions/bridge_search_token: -13%
  • ↓ bridgeUserActions/longTaskCount: -100%
  • ↓ bridgeUserActions/longTaskTotalDuration: -100%
  • ↓ bridgeUserActions/longTaskMaxDuration: -100%
  • ↓ bridgeUserActions/tbt: -100%
  • ↑ bridgeUserActions/inp: +92%
  • ↓ bridgeUserActions/fcp: -75%
  • ↑ bridgeUserActions/lcp: +875%

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

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

📈 Results compared to the previous 5 runs on main

  • ↓ startupStandardHome/firstReactRender: -99%
  • ↓ startupStandardHome/initialActions: -33%
  • ↑ startupStandardHome/setupStore: +74%
  • ↑ startupStandardHome/numNetworkReqs: +10%
  • ↓ startupStandardHome/longTaskCount: -33%
  • ↓ startupStandardHome/uiStartup: -29%
  • ↓ startupStandardHome/load: -23%
  • ↓ startupStandardHome/domContentLoaded: -23%
  • ↓ startupStandardHome/domInteractive: -41%
  • ↓ startupStandardHome/backgroundConnect: -12%
  • ↓ startupStandardHome/firstReactRender: -99%
  • ↓ startupStandardHome/initialActions: -50%
  • ↓ startupStandardHome/loadScripts: -23%
  • ↑ startupStandardHome/setupStore: +94%
  • ↓ startupStandardHome/fcp: -35%
  • ↓ startupStandardHome/lcp: -21%
User Journey Benchmarks · Samples: 5 · real API 🔴 1
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
🟡 total
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🔴 [CI log]
🔴 total

📈 Results compared to the previous 5 runs on main

  • ↓ onboardingImportWallet/doneButtonToHomeScreen: -95%
  • ↓ onboardingImportWallet/openAccountMenuToAccountListLoaded: -75%
  • ↓ onboardingImportWallet/longTaskCount: -100%
  • ↓ onboardingImportWallet/longTaskTotalDuration: -100%
  • ↓ onboardingImportWallet/longTaskMaxDuration: -100%
  • ↓ onboardingImportWallet/tbt: -100%
  • ↓ onboardingImportWallet/total: -89%
  • ↑ onboardingNewWallet/srpButtonToPwForm: +38%
  • ↑ onboardingNewWallet/createPwToRecoveryScreen: +25%
  • ↑ onboardingNewWallet/skipBackupToMetricsScreen: +42%
  • ↑ onboardingNewWallet/agreeButtonToOnboardingSuccess: +28%
  • ↓ onboardingNewWallet/doneButtonToAssetList: -85%
  • ↓ onboardingNewWallet/longTaskCount: -69%
  • ↓ onboardingNewWallet/longTaskTotalDuration: -79%
  • ↓ onboardingNewWallet/longTaskMaxDuration: -50%
  • ↓ onboardingNewWallet/tbt: -98%
  • ↓ onboardingNewWallet/total: -81%
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • ↓ dappPageLoad/pageLoadTime: -74%
  • ↓ dappPageLoad/domContentLoaded: -39%
  • ↓ dappPageLoad/firstPaint: -59%
  • ↓ dappPageLoad/firstContentfulPaint: -59%
Bundle Size Diffs [🚨 Warning! Bundle size has increased!]
Status Bundle Total Diff Change
🚨 background 15.62 MiB +39.05 KiB +0.24%
✅ ui 19.22 MiB -16.75 KiB -0.09%
✅ common 0 Bytes 0 Bytes 0.00%
✅ other 4.52 MiB -7.27 KiB -0.16%
🚨 content scripts 3.28 MiB +24.02 KiB +0.72%
🚨 zip 23.96 MiB +3.8 KiB +0.02%
### 🍒 What's in this RC

Cherry-picks (9 commits)
Commit Description
a13345c31d chore: update CHANGELOG.md
671a4c7f9e Update Attributions
efb2c305a2 fix: restore patched audit resolutions on 13.53.0 (#47091)
c817a82fc6 release(runway): cherry-pick fix: Infinite loading when sending with QR hardware wallet (#47088)
beaf2c56b6 Merge pull request #47086 from MetaMask/stable-sync-release-13.53.0
ead34182ea release: dedupe, update LavaMoat policies, update attributions
faeb05b16d fix: drop stale changelog unreleased link
374f1bfd6a Update LavaMoat policies
9ab2d6d859 Merge remote-tracking branch 'origin/release/13.53.0' into stable-sync-release-13.53.0

Changelog (51 commits since v13.52.0)
Commit Description
a13345c31d chore: update CHANGELOG.md
671a4c7f9e Update Attributions
efb2c305a2 fix: restore patched audit resolutions on 13.53.0 (#47091)
c817a82fc6 release(runway): cherry-pick fix: Infinite loading when sending with QR hardware wallet (#47088)
ead34182ea release: dedupe, update LavaMoat policies, update attributions
faeb05b16d fix: drop stale changelog unreleased link
374f1bfd6a Update LavaMoat policies
1cdf351332 release(runway): cherry-pick chore: update @metamask/stellar-wallet-snap to ^1.2.0 (#47084)
e44b2d5aa5 release(runway): cherry-pick bump: upgrade Bitcoin wallet Snap to 3.2.0 (#47062)
581d8f3b12 release(runway): cherry-pick bump(stellar): bump stellar-wallet-snap from 1.1.0 to 1.1.1 (#46975)
9d6ca502c5 release: release-changelog/13.53.0 (#46959)
793b5a26a3 Merge release/13.52.0 into release/13.53.0
ef01a4e848 Merge release/13.51.0 into release/13.53.0
a9ab17e357 feat: gate Discover search on basic functionality (#46874)
1bb09f44b9 feat: migrated popover component to use new DS (#46919)
4dc37d8bdd feat(networks): suggest Chainlist RPCs when adding an RPC URL (#46869)
88d92b789e fix(ramps): keep tags beside provider name in provider list item (#46942)
8a45df0505 fix(perps): apply the $10 minimum order check to limit orders (#46868)
0ef56f0c0a feat: sticky main tabs (#46931)
4d0b6b0600 chore: New Crowdin Translations by GitHub Action cp-13.52.0 (#46828)
c56d76f675 feat(confirmations): track MM Pay source account types (#46368)
8f2ff56185 test: fix flaky test phishing iframe warning (#46841)
c695c1506f chore: Bump @metamask/delegation-deployments from ^2.0.0 to ^2.1.0 (#46777)
a1fc2c5685 feat(networks): suggest Chainlist networks from the add network form (#46859)
e5aa9d57c4 test(assets): cover unified multichain and currency selectors (#46731)
12f5f2f334 chore: bump snaps solana@7.0.0 tron@4.0.0 bitcoin@3.1.0 (#46807)
0e9dae00a5 chore: remove the default address feature flag (#46873)
b927ee3577 fix: remove stale bridge (#46662)
4ab2870bc0 chore: onboarding sentry perf traces (#46896)
ba18c235de feat(confirmations): hint atomic max Money Account deposits (#46674)
19595a9e67 feat: restrict gasless 7702 delegations to Sentinel relay signers (#46809)
33dd28dbe4 test: Sync Feature Flag Registry - 2026-10-06 01:23 UTC (#46882)
847b50f04e test(assets): cover unified compatibility selectors (#46730)
f48b9266a9 fix: show Arc USDC balance and details from native asset cp-13.52.0 (#46840)
b59f7aa3d4 fix: return sidepanel to home after hardware wallet handoff (#46763)
dac297d43a fix(confirmations): pop pushed confirmation history on back (#46866)
e22db47960 fix(metrics): report money account type on deposit batches 13.52.0 (#46862)
0ab844a431 fix: stellar missing from send loader cp-13.52.0 (#46885)
f31507b0b7 fix(perps): freeze market list order (#46638)
182faf4caa feat: add X ticker widget (#45741)
71b70963f1 feat: track homepage critical user flows (#46612)
a234017027 test: tolerate failure for snap keyring tests (crash issue) (#46860)
7147923f89 fix: warn for add-network IDN homograph RPC urls (#46900)
d042c8da80 test(e2e): replace fragile generic tag selectors (#46395)
f6cd1028f9 release: Bump main version to 13.53.0 (#46850)
caf5f4eead fix(deep-links): verify configured signing hosts (#46755)
893cdd295a fix(deep-links): restrict handling to exact configured hosts (#46748)
af1c6ccc02 chore: revert "ci: unblock builds and tests while AWS OIDC is down" (#46925)
b335fda94e ci: unblock builds and tests while AWS OIDC is down (#46881)
a6765b12ed test: fix flaky test notifications account sync wait (#46774)
1c2d725f4c test: fix flaky test edit accounts add account wait (#46708)

AI Test Plan

Risk Score High Risk Medium Risk Files Changed Commits
52/100 5 7 239 54
Cherry-Pick Scenarios (2)

High Risk Scenarios (1)

1. QR Hardware Wallet - Send Flow Unblocked

Risk Level: HIGH

Why This Matters: Cherry-pick 47088 fixes an infinite loading issue in the QR signing flow; a regression here blocks users from sending funds with QR hardware wallets.

Test Steps:

  1. Add a QR-based hardware wallet (e.g., Keystone) via Add Hardware Wallet > QR and import an account.
  2. Send a small amount of ETH from that account; scan the signing QR with the device, then scan the device’s signature QR back into the extension.
  3. Verify the loading/progress view advances promptly to Submitted and then Confirmed without hanging.
  4. Repeat with an ERC-20 token transfer to confirm the fix covers token sends.

Medium Risk Scenarios (1)

1. QR Hardware Wallet - Error Handling and Retry

Risk Level: MEDIUM

Why This Matters: Cherry-pick 47088 fixes stuck states; validating error and retry paths ensures users can recover without re-importing or creating duplicate sends.

Test Steps:

  1. Start a QR signing flow and intentionally cancel/timeout on the device before returning the signature.
  2. Verify the extension exits loading with a clear error and presents Retry/Cancel (or equivalent) actions.
  3. Choose Retry, complete the scan sequence, and confirm exactly one transaction is submitted (no duplicates).

Release Scenarios (10)

High Risk Scenarios (4)

1. Hardware Wallet (Ledger) - Transaction Signing and Send

Risk Level: HIGH

Why This Matters: Large refactor in the Ledger offscreen handler can break connection lifecycle and signing flows, impacting users who rely on hardware wallets for security-critical transactions.

Test Steps:

  1. Connect a Ledger via USB, open the Ethereum app, and add it via Settings > Advanced > Hardware Wallets > Ledger.
  2. Import a Ledger account and initiate a send of a small amount of ETH on Ethereum Mainnet to a known address.
  3. Confirm the transaction on the Ledger; verify the extension shows the correct prompts and transitions from Pending to Confirmed.
  4. From a test dapp (e.g., EIP-712 demo), request a typed data signature and sign on Ledger; confirm the dapp resolves and activity is recorded.

2. Transaction Flow - Transaction Pay Controller Integration

Risk Level: HIGH

Why This Matters: New controller initialization in the transaction pipeline can cause regressions in submission, replacement (speed up), and cancellation handling.

Test Steps:

  1. Initiate an ERC-20 approval from a dapp and submit; verify fee display and confirmation proceed without errors.
  2. While the approval is pending, use Speed Up and confirm; verify the replacement transaction updates correctly.
  3. Attempt to Cancel the pending approval; confirm status updates to Canceled and the dapp surfaces the correct error.
  4. Send a simple ETH transfer from the account; verify no regressions in estimates, submission, or status updates.

3. Transaction/Signature Restore After Extension Reload

Risk Level: HIGH

Why This Matters: Changes in messenger-client init and controller wiring can break pending approval restoration, causing stuck dapp flows and loss of user actions.

Test Steps:

  1. Trigger a signature request (personal_sign) from a dapp and do not approve; close the popup.
  2. Reload the extension (via chrome://extensions) and reopen the MetaMask popup.
  3. Verify the pending signature request is restored and actionable; approve it and confirm the dapp resolves.
  4. Repeat with a pending token approval to ensure both tx and signature approvals persist and restore correctly.

4. Multichain Accounts - Default Address Indicator and Copy

Risk Level: HIGH

Why This Matters: Hook and preferences changes can desync the default address state, confusing users and risking mis-sends.

Test Steps:

  1. In the multichain accounts view, mark an account as the default address (via row action/star).
  2. Switch between Ethereum and another supported network (e.g., Polygon/Base) and revisit the accounts list.
  3. Verify the default address badge/indicator is consistently shown across networks and on the account overview.
  4. Use the copy icon on the network group; verify the copied address is correct for the selected account and persists after locking/unlocking the extension.

Medium Risk Scenarios (6)

1. Security Trust Inline Badge - Visibility and Details

Risk Level: MEDIUM

Why This Matters: UI logic changes can misrepresent trust levels or obstruct core actions on critical approval screens.

Test Steps:

  1. Enable the security provider in Settings > Security & Privacy.
  2. Connect to a test dapp and open an approval/permission screen; observe whether the inline trust badge renders appropriately (Trusted/Unknown/Risky).
  3. Click the badge to open details; verify correct text, no layout overlap, and accessibility of the main action buttons.
  4. Repeat on a well-known site to ensure the badge hides or shows as expected.

2. Token List - Search, Hide/Unhide, Network Switching

Risk Level: MEDIUM

Why This Matters: Token list changes risk incorrect filtering, state sync, and visibility toggles—leading to user confusion or missing assets.

Test Steps:

  1. Open the Assets > Tokens tab; search for a token by name/symbol and verify correct filtering.
  2. Hide a token via its context or overflow menu; confirm it disappears and can be recovered via Manage tokens/Hidden list.
  3. Switch networks (e.g., Ethereum to Polygon) and verify token list/balances refresh correctly with no duplicates or stale entries.

3. Coin Overview - Quick Actions (Buy/Swap/Send/Receive)

Risk Level: MEDIUM

Why This Matters: Changes to the coin overview can break entry points to core flows (buy/swap/send/receive) and cause mis-estimates or wrong addresses.

Test Steps:

  1. Open the native coin overview and click Buy then cancel; then click Swap and verify prefilled asset and quote loading; cancel.
  2. Open a token’s overview and Send a small amount; verify gas estimation, confirmation, and post-transaction balance updates.
  3. Open Receive on both native coin and a token; verify correct address and QR rendering.

4. Account Overview Layout - Navigation and Responsiveness

Risk Level: MEDIUM

Why This Matters: Layout updates can introduce visual regressions that hide actions or mislead users about balances and activity.

Test Steps:

  1. Open the account overview and toggle between Assets and Activity; verify loading states, totals, and empty states.
  2. Resize the extension popup (narrow to wide) and ensure layout and badges remain aligned without clipping.
  3. Switch networks and return; confirm the layout remains stable and reflects the correct network context.

5. Hardware Wallet (Ledger) - Offscreen Recovery and Reconnection

Risk Level: MEDIUM

Why This Matters: Offscreen handling changes can cause connection drops or stuck states when the extension is backgrounded or the OS sleeps.

Test Steps:

  1. Start a Ledger signing flow; minimize/blur the extension and wait ~30 seconds.
  2. Approve on the Ledger, then refocus the extension; verify the flow resumes and submits without a reconnect prompt.
  3. Lock and unlock the OS, then attempt another signing; confirm the connection recovers and no orphaned loading screen appears.

6. Assets Persistence Across Upgrade

Risk Level: MEDIUM

Why This Matters: Subtle state/migration or selector changes can cause missing or duplicated assets after an upgrade.

Test Steps:

  1. Use a profile with several custom watched tokens and NFTs; update to this release build.
  2. Open Assets and verify all watched items and balances are present and ordered as before.
  3. Initiate one token transfer to ensure metadata (decimals/symbol) remains consistent post-upgrade.

Teams Sign-off Status

Signed off: None yet

Awaiting sign-off (8):
Accounts, Assets, Confirmations, Networks, Security, Swaps, Transactions, Wallet


Generated by AI Test Plan Analyzer (gpt-5) at 2026-10-19T18:37:55.433Z

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

@sleepytanya
sleepytanya marked this pull request as ready for review October 19, 2026 18:52

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modern web / Chrome extension review

Reviewed client-facing changes under ui//shared/ and extension work under app/ (especially the new X cashtag content script + widget). Most of the new UI follows current patterns well (native <dialog>/Popover, invoker commands, anchor positioning, frame-ancestors for the embedded widget).

Actionable items below are limited to the X timeline injection path, where main-thread cost and Baseline gaps are most likely to show up in production.

Open in Web View Automation 

Sent by Cursor Automation: Modern web guidance


scan(document);

const observer = new MutationObserver((mutations) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chrome extension content-script perf: This MutationObserver runs scan() synchronously for every added subtree. On X’s infinite-scroll feed that can mean large querySelectorAll + per-anchor replaceChildren() work inside a single observer callback, blocking the page main thread.

Please batch visual DOM work (e.g. collect anchors first, then paint in chunks via requestAnimationFrame, yielding with scheduler.yield() when available), matching the content-script guidance for heavy DOM updates.


scan(document);

const observer = new MutationObserver((mutations) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same main-thread concern as pill injection: the observer here can run scan()/prune() synchronously across big DOM subtrees as tweets stream in. Consider deferring scan work to idle/rAF batches so hover/scroll on X stays responsive.

if (mounted.has(element)) {
return;
}
element.setAttribute('interestfor', popoverId);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modern web Baseline / fallback: Widget open/hover is wired through interestfor + :interest-source with no feature detection or fallback. This release already adds an explicit Interest Invoker capability check + fallback path in ui/pages/ramps/payment-method/components/ramps-quote-display.tsx.

Without a similar guard (polyfill or click/focus fallback), browsers without native Interest Invokers get pills but no popover/widget. Recommend detecting 'interestFor' in HTMLAnchorElement.prototype (or equivalent) and providing a degraded open path before rollout.

@sleepytanya
sleepytanya merged commit ab70b95 into stable Oct 19, 2026
133 of 134 checks passed

This branch had an error being deployed

1 failed (outdated), 2 active (outdated), and 3 inactive (1 outdated) deployments
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-13.53.0 Issue or pull request that will be included in release 13.53.0 team-bots Bot team (for MetaMask Bot, Runway Bot, etc.)

Projects

None yet

Development

Successfully merging this pull request may close these issues.