Skip to content

Comments

release: 13.20.0#40258

Draft
metamaskbot wants to merge 85 commits intostablefrom
release/13.20.0
Draft

release: 13.20.0#40258
metamaskbot wants to merge 85 commits intostablefrom
release/13.20.0

Conversation

@metamaskbot
Copy link
Collaborator

@metamaskbot metamaskbot commented Feb 19, 2026

🚀 v13.20.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 Framework
  • Assets
  • Bots Team
  • Confirmations
  • Core Extension UX
  • Core Platform
  • Engagement
  • Extension Platform
  • Mobile UX
  • Network Enablement
  • Networks
  • Onboarding
  • Perps
  • Product Safety
  • Shield
  • Swaps and Bridge

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

HowardBraham and others added 30 commits February 12, 2026 22:51
## **Description**

We can't get a release out because:

1. Download `test-runs-for-splitting` is failing (maybe it's because we
don't have any recent runs on branch `main` that have `status:success`,
but I'm not sure)
2. `test/e2e/tests/deep-link/deep-link.spec.ts` on `firefox-webpack`
runs incredibly long (I've talked about this recently)
3. It's not splitting intelligently, and it's hitting the timeout of 30
minutes

## **Changelog**

CHANGELOG entry: null

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> CI-only change that lengthens E2E job/test execution timeouts; no
product code or security-sensitive logic is modified.
> 
> **Overview**
> Increases the `run-e2e` GitHub Actions workflow timeout from **30 to
40 minutes**, both at the job level (`timeout-minutes`) and the default
for the `test-timeout-minutes` workflow input used by the test step.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
cf04291. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Version Bump After Release

This PR bumps the main branch version from 13.19.0 to 13.20.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.19.0` to `13.20.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.19.0
- Release branch: release/13.19.0
- Platform: extension
- Test mode: false

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Version metadata-only change with no runtime logic impact; risk is
limited to downstream build/release tooling expecting a specific
version.
> 
> **Overview**
> Bumps the extension package version in `package.json` from `13.19.0`
to `13.20.0` to keep `main` ahead of the release branch for
nightly/build/update-channel alignment.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7e72e73. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
…9931)

## **Description**

Optimize gas fees for Shield crypto subscription approval transactions
to reduce over-funding during gas sponsorship.

**Changes:**
1. Implement gas fee optimization formula: `min(2 * low, medium)` for
priority fees on EIP-1559 networks
2. Use `useGasFeeEstimates` hook to get real-time gas estimates for the
target chain
3. Set `disableGasBuffer: true` to prevent automatic gas limit buffering
by TransactionController
4. Remove redundant manual `estimateGas` call (TransactionController
handles this internally)

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/39931?quickstart=1)

## **Changelog**

CHANGELOG entry: Optimized gas fees for Shield crypto subscription
transactions to reduce sponsorship costs

## **Related issues**

Fixes: SUBS-814

## **Manual testing steps**

1. Go to Settings > Shield > Subscribe with Crypto
2. Select a token on an EIP-1559 network (e.g., Ethereum mainnet)
3. Initiate a subscription approval transaction
4. Verify in the confirmation screen that `maxPriorityFeePerGas` uses
the optimized formula
5. Complete the transaction and verify it succeeds with lower gas costs

## **Screenshots/Recordings**

### **Before**

N/A - Internal gas fee changes, no UI changes

### **After**

N/A - Internal gas fee changes, no UI changes

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] 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)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches transaction-parameter construction for subscription approval
flows; mistakes could lead to underpriced transactions or failures on
EIP-1559 networks, though guarded by estimate-type checks and tests.
> 
> **Overview**
> Reduces over-funding of Shield crypto subscription approval
transactions by overriding the EIP-1559 `maxPriorityFeePerGas` on
`shieldSubscriptionApprove` transactions using **`min(2 × low,
medium)`** from live `useGasFeeEstimates` for the token’s chain.
> 
> Adds a focused unit test suite for
`useSubscriptionCryptoApprovalTransaction` covering fee-market vs legacy
networks and missing/invalid estimates, and updates the Jest console
baseline to allow the new test’s Router warnings.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e1d6549. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

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

## **Description**

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

Users can bypass the entire onboarding flow by navigating directly to
the completion route (`#/onboarding/completion`), rendering the
`CreationSuccessful` component without having created a wallet. Clicking
"Open wallet" then calls `completeOnboarding()`, marking onboarding as
complete even though the KeyringController vault was never created. This
leads to an inconsistent state where the extension appears onboarded but
has no wallet, causing errors when trying to unlock.

This PR adds a guard to the `CreationSuccessful` component that checks
whether the wallet has been initialized (`isInitialized`). If the wallet
is not initialized and the user is not arriving from a settings
reminder, they are redirected back to the onboarding welcome page. This
prevents users from skipping mandatory onboarding steps by directly
manipulating route URLs.

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/40012?quickstart=1)

## **Changelog**

CHANGELOG entry: Fixed a security issue where users could skip
onboarding by navigating directly to the completion route

## **Related issues**

Fixes: #37079

## **Manual testing steps**

1. Load the extension in Chrome and begin a fresh onboarding (clear
extension data if needed)
2. Instead of going through the onboarding flow, navigate directly to
`chrome-extension://<extension-id>/home.html#/onboarding/completion`
3. Verify that you are redirected back to the onboarding welcome page
instead of seeing the "Your wallet is ready!" screen
4. Complete the normal onboarding flow (create password, back up SRP,
etc.)
5. Verify the completion screen renders correctly after proper
onboarding
6. After onboarding, go to Settings → Security & Privacy → Reveal Secret
Recovery Phrase → back up SRP again
7. Verify the completion screen renders correctly when arriving from the
settings reminder flow (`?isFromReminder=true`)

## **Screenshots/Recordings**

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

### **Before**

<!-- Navigating directly to `#/onboarding/completion` shows the "Your
wallet is ready!" screen and allows completing onboarding without a
wallet -->

### **After**

<!-- Navigating directly to `#/onboarding/completion` redirects to the
welcome page -->

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

Follow up to the workaround in
3345f3e

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/39471?quickstart=1)

## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Related to: #39464
<!--
## **Manual testing steps**

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

## **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**
> Small, targeted state cleanup that only removes keys when explicitly
set to `null`; changes are covered by focused unit tests and fixture
version bumps.
> 
> **Overview**
> Adds migration `194` that **cleans persisted root state** by deleting
`seedWords` and `forgottenPassword` only when the keys exist and their
values are `null`, recording the deletions in `changedKeys`.
> 
> Registers the new migration in `migrations/index.js`, adds unit tests
covering null/non-null/missing-key cases, and updates e2e fixtures/state
snapshots to expect `version`/`currentMigrationVersion` `194`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
913c96f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=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 fixes the `accessToken` not being persisted across lock/unlock
cycles issue in the seedless onboarding flow and upgrades
`@metamask/seedless-onboarding-controller` from v7.1.0 to v8.0.0.

**Problem:**
Previously, the `OAuthService` was reading the `accessToken` directly
from `SeedlessOnboardingController` state via
`SeedlessOnboardingController:getState`. The access token was not
persisted in the controller state, causing it to be lost after a
lock/unlock cycle. Additionally, when the token expired, there was no
mechanism to automatically refresh it before making API calls (e.g.,
marketing opt-in).

**Solution:**
- Updated to `@metamask/seedless-onboarding-controller` v8.0.0 which
exposes a new `SeedlessOnboardingController:getAccessToken` action that
handles token retrieval and automatic refresh when expired.
- Replaced direct state access (`SeedlessOnboardingController:getState`
→ `accessToken`) with the new
`SeedlessOnboardingController:getAccessToken` action in `OAuthService`.
- Improved error handling in `BaseLoginHandler` by introducing
`createErrorFromNetworkRequest` utility to provide more descriptive
error messages (including status codes and response body) for
token-related network failures (auth token, refresh, revoke, renew).
- Added new `OAuthErrorMessages` enum entries for granular error
categorization.
- Removed the unused `NO_AUTH_CODE_FOUND_ERROR` enum value and updated
the welcome page error handling accordingly.
- Added E2E tests to verify token refresh behavior and access token
validity after lock/unlock cycles.

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/40013?quickstart=1)

## **Changelog**

CHANGELOG entry: Fixed access token not persisting across lock/unlock
cycles for seedless onboarding users

## **Related issues**

Fixes: #39566
Relates to: #40011

## **Manual testing steps**

1. Enable seedless onboarding feature flag and start a dev build (`yarn
start`)
2. Go through the seedless onboarding flow using social login (Google)
3. After onboarding completes, lock the wallet
4. Unlock the wallet with your password
5. Navigate to Settings → Privacy & Security
6. Verify that the marketing consent settings load correctly (this
confirms the access token was refreshed and used successfully)
7. Verify no errors appear in the console related to "No access token
found"

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches seedless onboarding OAuth token retrieval/refresh paths and
bumps a core controller dependency, which could affect authentication
and downstream API calls if integration mismatches. Changes are
mitigated by added unit/E2E coverage around failure cases and
lock/unlock refresh flows.
> 
> **Overview**
> Fixes seedless onboarding marketing-consent calls failing after
lock/unlock by switching `OAuthService` to fetch tokens via the new
`SeedlessOnboardingController:getAccessToken` action (delegated through
the OAuth service messenger/types) instead of reading `accessToken` from
controller state.
> 
> Improves OAuth/Auth-server failure visibility by adding
`createErrorFromNetworkRequest` and expanding `OAuthErrorMessages`, then
wiring these into `BaseLoginHandler` (token/refresh/revoke/renew) and
updating unit tests accordingly; also removes the unused
`NO_AUTH_CODE_FOUND_ERROR` handling in the onboarding welcome UI.
> 
> Upgrades `@metamask/seedless-onboarding-controller` to `^8.0.0` and
adds/updates E2E mocking + a new E2E spec to validate token refresh
behavior and access-token validity across lock/unlock cycles.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
5db5ced. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

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

## **Description**

This PR refactors the Solana test dapp page object to use a more
efficient element verification pattern. Instead of finding elements and
then asserting their text content separately, the code now uses
`waitForSelector` with the `text` parameter to verify elements in a
single operation.

**Changes:**
- Replaced `getConnectionStatus()` and `getAccount()` getter methods
with `verifyConnectionStatus()` and `verifyAccount()` verification
methods
- Updated verification methods to use `waitForSelector()` with `text`
parameter instead of `findElement()` + `getText()` + assertion pattern
- Moved all locators to the top of the class in alphabetical order for
better organization
- Created locator methods that accept text parameters (`accountLocator`
and `connectionStatusLocator`)
- Updated `connect.spec.ts` test file to use the new verification
methods and removed unused assertion helper imports

**Benefits:**
- More concise and readable test code
- Better performance by combining element location and text verification
in a single operation
- Improved maintainability with centralized locator definitions
- Consistent with E2E testing best practices

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/39779?quickstart=1)

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MMQA-1200

## **Manual testing steps**

1. Run the Solana Wallet Standard E2E tests: `yarn test:e2e:single
test/e2e/flask/solana-wallet-standard/connect.spec.ts --browser=chrome`
2. Verify all tests pass with the refactored page object methods
3. Confirm that connection status and account verification work
correctly

## **Screenshots/Recordings**

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

### **Before**

N/A - Internal refactoring only

### **After**

N/A - Internal refactoring only

## **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 are limited to E2E test/page-object logic, but multiple
scenarios are now skipped and the new selector+text verification could
alter test reliability/coverage if locators or displayed text differ.
> 
> **Overview**
> Refactors the Solana test dapp page object header API to *verify* UI
state via `waitForSelector` + expected `text` (new
`verifyConnectionStatus`/`verifyAccount`) instead of reading values
(`getConnectionStatus`/`getAccount`) and asserting separately; also
centralizes button/status/account locators and reuses them for clicks.
> 
> Updates `connect.spec.ts` to use the new verification helpers, drops
the `assertConnected`/`assertDisconnected` imports, and marks several
connect/disconnect/switch/refresh scenarios as `it.skip` with TODOs due
to current mismatches/flaky expectations (e.g., "Not connected" vs
"Disconnected", unexpected account shown).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
119cd23. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

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

On PulseChain, confirmation could show a fiat value for **Network fee**
even when fiat conversion is unavailable elsewhere in the app (home for
example). This happened when the chain conversion rate was missing/null
and fee formatting still produced a fiat-like fallback (`< $0.01`).

## Problem

`useFeeCalculations` was generating fiat display values even when
conversion rate was invalid/missing, creating inconsistent behavior
across surfaces.

## Solution

- Require a valid conversion rate (`finite && > 0`) before producing gas
fee fiat values.
- If conversion rate is unavailable, return empty fiat values from fee
calculations instead of `"< $0.01"`.
- Update confirmation fee rows to render fiat only when a fiat value
actually exists:
- `EditGasFeesRow` now falls back to native fee display when fiat is
unavailable.
  - `GasFeesRow` skips rendering fiat text when fiat is empty.
- Remove temporary debug/console logging.
- Update affected unit tests for the new expected behavior.



## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes: #39836

## **Manual testing steps**

1. Use PulseChain account with PLS balance.
2. Confirm home/send views show no fiat conversion for PLS.
3. Start a send and proceed to confirmation.
4. Verify **Network fee** no longer shows fiat when conversion rate is
unavailable, and shows native-only fee consistently.


## **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**
> UI/formatting logic changes limited to fee display when conversion
rates are missing; no transaction signing or fee computation semantics
change beyond suppressing fiat output.
> 
> **Overview**
> Confirmation fee calculations now require a *valid* chain conversion
rate (finite and > 0) before producing fiat-formatted gas fees;
otherwise fiat outputs are returned empty instead of the `"< $0.01"`
fallback.
> 
> Confirmation UI fee rows (`EditGasFeesRow`, `GasFeesRow`) now only
render fiat amounts when a non-empty fiat value exists, falling back to
native-only display when conversion data is unavailable. Tests and mocks
are updated accordingly (including expanded spot price mocks for BSC in
the gas estimates e2e spec).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
76351a2. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Initial support for MetaMask Pay in dApp transaction confirmations.

Currently disabled unless `MM_PAY_DAPPS_ENABLED` set.

### New Components
- `TransactionPaySection` - Container component that orchestrates the
pay flow UI, gated by `MM_PAY_DAPPS_ENABLED`
- `RequiredTokensRow` - Displays required tokens with amount/asset pills
and fiat values

### Modified Components
- `PayWithRow` - Added `variant` prop for Default (pill styling) vs
Small (inline) display
- `BridgeFeeRow` - Added `variant` prop; Default hides MetaMask fee,
Small shows it
- `TotalRow` - Added `variant` prop for consistent styling across
contexts
- `BridgeTimeRow` - Added `rowVariant` prop for size control
- `GasFeeSection` - Hide when `sourceAmounts` exist (Pay flow handles
fees)
- `TokenIcon` - Added `xs` size (16px) for compact displays

### Integration
- Integrated `TransactionPaySection` into `BaseTransactionInfo`,
`NativeTransferInfo`, `TokenTransferInfo`
- Added `ConfirmInfoRowSize` enum export from row component

## **Changelog**

CHANGELOG entry: null

## **Related issues**

## **Manual testing steps**

## **Screenshots/Recordings**

### **Before**

### **After**

<img width="379" height="625" alt="Confirmation"
src="https://github.com/user-attachments/assets/e1dfe968-040e-4920-af14-38b14c01972d"
/>

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches transaction confirmation UI/logic and upgrades
`@metamask/transaction-pay-controller`, which can affect fee/payment
presentation and transaction flows, though the new Pay section is gated
by `MM_PAY_DAPPS_ENABLED`.
> 
> **Overview**
> Adds initial *MetaMask Pay* support to dapp transaction confirmations
behind `MM_PAY_DAPPS_ENABLED`, inserting a new `TransactionPaySection`
(with `RequiredTokensRow`, `PayWithRow`, and optional fee/total rows)
into the main confirmation info flows.
> 
> Updates confirmation rows to support size variants and improved
loading states (new labeled skeleton behavior, compact `PayWithRow` pill
UI, and variant-driven `BridgeFeeRow`/`BridgeTimeRow`/`TotalRow`
rendering), and hides `GasFeesSection` when pay `sourceAmounts` are
present.
> 
> Wires additional permitted-account lookups into
`wallet_getCapabilities`/`wallet_sendCalls`, adds the `requiredToken`
i18n string, introduces `TokenIcon` `xs` size, and bumps
`@metamask/transaction-pay-controller` (plus related LavaMoat policy and
lockfile dependency updates).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
92216ea. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
…on (#40027)

## **Description**

Updates the "learn more" links for smart accounts to point to the
specific section on the support page.

**What is the reason for the change?**
The current links point to the top of the support article. Users should
be directed to the specific section about MetaMask smart accounts for a
better support experience.

**What is the improvement/solution?**
Updated the URL from
`https://support.metamask.io/configure/accounts/what-is-a-smart-account`
to
`https://support.metamask.io/configure/accounts/what-is-a-smart-account/#what-are-metamask-smart-accounts`
in two files:
- `shared/lib/ui-utils.js` (`SMART_ACCOUNT_INFO_LINK`)
- `ui/helpers/constants/zendesk-url.js` (`ACCOUNT_UPGRADE`)

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/40027?quickstart=1)

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: MetaMask/MetaMask-planning#4861

## **Manual testing steps**

1. Go Accounts menu > accounts detail > smart account set up.
2. Click the "learn more" link.
3. Verify that the link navigates to
`https://support.metamask.io/configure/accounts/what-is-a-smart-account/#what-are-metamask-smart-accounts`
and scrolls to the correct section.


## **Screenshots/Recordings**

### **Before**

Links navigate to
`https://support.metamask.io/configure/accounts/what-is-a-smart-account`
(top of page).

### **After**

Links navigate to
`https://support.metamask.io/configure/accounts/what-is-a-smart-account/#what-are-metamask-smart-accounts`
(specific section).

<img width="1197" height="935" alt="Screenshot 2026-02-12 at 15 26 56"
src="https://github.com/user-attachments/assets/718c84c0-0ea4-4170-8583-14494db16ecd"
/>
<img width="1195" height="929" alt="Screenshot 2026-02-12 at 15 29 30"
src="https://github.com/user-attachments/assets/d732f3b0-f2b3-4375-b9b0-6490fde97741"
/>

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> String-only URL updates with no behavior changes beyond where external
links land.
> 
> **Overview**
> Updates the smart account “learn more” URLs to deep-link to the
`#what-are-metamask-smart-accounts` section instead of the top of the
support article.
> 
> This changes both `SMART_ACCOUNT_INFO_LINK` in
`shared/lib/ui-utils.js` and `ZENDESK_URLS.ACCOUNT_UPGRADE` in
`ui/helpers/constants/zendesk-url.js`, affecting any UI that opens those
links.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e83fc8a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=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**

Improve handling of scenario when gas estimation fails.

## **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: MetaMask/MetaMask-planning#6388

## **Manual testing steps**

1. Mock gas estimations to fail and submit a transaction
2. Check that Unavailable is displayed for gas
3. Update to custom value and see that alert and unavailable goes away

## **Screenshots/Recordings**


https://github.com/user-attachments/assets/3b372807-18f6-45e6-8bd1-111442d00249

## **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**
> UI-level conditional rendering and new hook logic around existing
`simulationFails`/`userFeeLevel`, with updates isolated to confirmations
and tests.
> 
> **Overview**
> Improves confirmations UX when gas estimation fails by introducing
`useEstimationFailed` (simulation failure *and* non-`CUSTOM`
`userFeeLevel`) and reusing it for the gas-estimate warning alert.
> 
> When estimation has failed and gas isn’t sponsored, the gas fee row
now shows **"Unavailable"** and hides fiat/token values and advanced fee
breakdown fields (e.g., L1/L2 and max fee); sponsored-gas flows continue
to show "Paid by MetaMask". Tests/fixtures and i18n strings are updated
accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
acb8b3f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Move props closer to point of usage

Part of breaking down the Activity v2 PR

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/40077?quickstart=1)

## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Small UI refactor that changes how the modal sources the “from”
address; main risk is incorrect display if `getSelectedAccount` is unset
or differs from the transaction’s actual sender.
> 
> **Overview**
> **Refactors `MultichainTransactionDetailsModal` to stop requiring a
`userAddress` prop**, and instead derives the address from Redux via
`getSelectedAccount`.
> 
> Updates the non‑EVM transaction list and unified transaction list to
stop passing `userAddress`, and adjusts the modal test
setup/expectations (including seeding `internalAccounts` so Bitcoin
“from” renders as the account name rather than a shortened address).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
831696b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…failing to transfer on new chromium-based browsers (#40101)

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

Update `extension-port-stream` to `v5.0.3` to fix an issue with users
with a lot of state who are on recent version of chromium, caused by a
change in behavior in chromium.

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

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/40101?quickstart=1)

## **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: fixes issue for users with a lot of state on recent
chromium-based browsers

## **Related issues**

Fixes: #40082
<!--
## **Manual testing steps**

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

## **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**
> Dependency-only patch version bump with lockfile updates; limited
surface area beyond whatever behavior changed upstream in
`extension-port-stream`.
> 
> **Overview**
> Updates the `extension-port-stream` dependency from `^5.0.2` to
`^5.0.3`, including the corresponding `yarn.lock` resolution/checksum
changes, to address a Chromium behavior change impacting users with
large extension state.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
8a91fd9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=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**

Reverts #39565 

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/39945?quickstart=1)

## **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: revert: remove network dropdown from Activity tab

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

[skip-e2e]

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches core Activity filtering/rendering across multiple list
implementations and changes which transactions appear based on
enabled-network state, which could hide/show activity unexpectedly if
selectors or chain-ID handling are wrong.
> 
> **Overview**
> Restores the **network dropdown** control in the Activity/transaction
lists by rendering `AssetListControlBar` again (with a new
`hideNetworkFilter` prop to suppress it in embedded contexts like the
asset page).
> 
> Updates both `TransactionList` and `UnifiedTransactionList` to
**filter pending/completed activity by enabled networks**, including
special handling for MetaMask Pay transaction types via a new
`filterTransactionByChain` helper (with unit tests). E2E and snapshot
tests were adjusted to reflect the restored dropdown and updated
activity assertions.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7ddab7e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Adds custom toast notifications for the mUSD Merkl rewards claiming
flow. When a user initiates a Merkl claim transaction, the toast tracks
the transaction lifecycle: in-progress (with spinner) → success/failed
(auto-hides after 5s).

Also fixes a pre-existing bug in `home.component.js` where the "network
added" notification would reappear after navigating away and back —
`onAutoHide` was calling the raw `setEditedNetwork()` action creator
(no-op) instead of the dispatched `clearEditedNetwork()` prop.

**Changes:**
- `useMerklClaimStatus` hook — monitors Redux transactions for Merkl
Distributor address, detects pending → confirmed/failed/dropped
transitions, and exposes `toastState` + `dismissToast`
- `MerklClaimToast` component in `ToastMaster` — renders loading spinner
(in-progress), checkmark (success), or error icon (failed) using
`@metamask/design-system-react` icons
- 3 new i18n strings for toast messages
- Bug fix: `home.component.js` `onAutoHide` now calls
`clearEditedNetwork()` (dispatched) instead of `setEditedNetwork()`
(undispatched import)

**Note:** This has been tested together with the full `claim-musd`
branch changes from [PR
#39901](#39901)
(Merkl rewards functionality — still WIP), but this PR is independent
and can be merged first.


## **Changelog**

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

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

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

CHANGELOG entry: Added toast notifications for mUSD reward claim
transaction status (in-progress, success, failed); fixed a bug where the
"network added" home notification would reappear after navigation

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MUSD-303

## **Manual testing steps**

1. Apply the full Merkl claiming changes from the `claim-musd` branch
(PR #39901) on top of this branch
2. Hold mUSD with unclaimed Merkl rewards, claim via the Claim flow
3. Verify the "Your mUSD bonus is processing" toast appears with a
spinning loader
4. After transaction confirms, verify "Your mUSD bonus is here!" toast
appears with a checkmark and auto-hides after 5 seconds
5. Reject a claim transaction — verify "Bonus claim failed" toast
appears with an error icon
6. For the bug fix: add a custom network, wait for the "successfully
added" notification to auto-hide, navigate away and back — verify it
does NOT reappear

## **Screenshots/Recordings**

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

### **Before**

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

### **After**


https://github.com/user-attachments/assets/27e072c2-e64b-4d63-b95b-c38bba79ed68


<!-- [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**
> Adds new UI toast behavior driven by transaction state transitions;
low blast radius but mistakes could cause noisy/incorrect user
notifications or missed claim feedback.
> 
> **Overview**
> Adds mUSD Merkl rewards claim status toasts that watch Merkl
distributor transactions and show *in-progress* (spinner) then
*success*/*failed* completion messages (auto-hiding after 5s).
> 
> Introduces a new `useMerklClaimStatus` hook (with tests) to detect
pending→confirmed/failed/dropped transitions and prevent duplicate
completion toasts, wires it into `ToastMaster`, and adds new i18n
strings.
> 
> Fixes `home.component.js` notification auto-hide to call the
dispatched `clearEditedNetwork()` instead of an undispatched
`setEditedNetwork()` action creator.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
10cb57e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…39921)

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

- **Reason for the change**: When signing a swap of ERC20 USDC (and
similar token operations) on Base, Polygon, etc with a Ledger device,
the device showed "_Review transaction to manage NFT allowance_" even
though the transaction was a token (ERC20) approve, not an NFT one.
- **Root cause**: Ledger’s clear-sign resolution in
`@ledgerhq/hw-app-eth` is based only on the transaction’s 4-byte
selector. In `@ledgerhq/evm-tools`, ERC20 and ERC721 use the same
selector for `approve()`: `0x095ea7b3`. With `nft: true` in the
resolution config, the library enables both ERC20 and NFT resolution for
any call with that selector. The device then receives NFT plugin data
and shows the NFT allowance message even when the contract is an ERC20.
- **Proposed fix**: We set the nft resolution flag by transaction
selector instead of always passing `nft: true`. We parse the raw tx to
get the 4-byte selector and only pass `nft: true` when the selector is
NFT-only (used by ERC721/ERC1155 but not by ERC20): e.g.
`setApprovalForAll` (`0xa22cb465`), `safeTransferFrom` (`0x42842e0e`,
`0xb88d4fde`, `0xf242432a`), `safeBatchTransferFrom` (`0x2eb2c2d6`). For
the shared approve selector (`0x095ea7b3`) and all other selectors we
pass `nft: false`, so ERC20 approves only get ERC20 resolution and the
device shows the correct token/allowance wording. Real NFT transfers and
approvals still get `nft: true` and keep NFT clear signing.
- The other excluded selector is `transferFrom` (`0x23b872dd`) since it
could also be used by ERC20 and ERC721

### Technical Details

- ERC20: https://eips.ethereum.org/EIPS/eip-20

```solidity
// Source: https://github.com/openzeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol

interface IERC20 {
  // Partial snippet from the interface

  function transfer(address to, uint256 value) external returns (bool);

  function approve(address spender, uint256 value) external returns (bool);

  function transferFrom(address from, address to, uint256 value) external returns (bool);
}
```

- ERC721: https://eips.ethereum.org/EIPS/eip-721

```solidity
// Source: https://github.com/openzeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/IERC721.sol 

interface IERC721 is IERC165 {
  // Partial snippet from the interface

  function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;

  function safeTransferFrom(address from, address to, uint256 tokenId) external;

  function transferFrom(address from, address to, uint256 tokenId) external;

  function approve(address to, uint256 tokenId) external;

  function setApprovalForAll(address operator, bool approved) external;
}
```

- ERC1155: https://eips.ethereum.org/EIPS/eip-1155

```solidity
// https://github.com/openzeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC1155/IERC1155.sol

interface IERC1155 is IERC165 {
  // Partial snippet from the interface

  function setApprovalForAll(address operator, bool approved) external;

  function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;

  function safeBatchTransferFrom(
    address from,
    address to,
    uint256[] calldata ids,
    uint256[] calldata values,
    bytes calldata data
  ) external;
}
```



Selector | ERC-20 | ERC-721 | ERC-1155
-- | -- | -- | --
0x23b872dd | ✅ | ✅ | ❌
0x095ea7b3 | ✅ | ✅ | ❌
0xa22cb465 | ❌ | ✅ | ✅
0xa9059cbb | ✅ | ❌ | ❌
0x42842e0e | ❌ | ✅ | ❌
0xb88d4fde | ❌ | ✅ | ❌
0xf242432a | ❌ | ❌ | ✅
0x2eb2c2d6 | ❌ | ❌ | ✅

</div></div> 

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/39921?quickstart=1)

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

## **Manual testing steps**

1. Import a Ledger account into MetaMask
2. Try to swap a ERC20 token like USDC in Base
3. Verify that the message displayed in the ledger (Ledger Nano 5, Flex,
or Stax) is about ERC20 tokens and not NFTs

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches hardware-wallet transaction signing parameters; incorrect
selector parsing or allowlist coverage could regress Ledger clear-sign
behavior for some contract calls.
> 
> **Overview**
> Fixes Ledger clear-signing resolution by **deriving the `nft` flag
from the transaction’s 4-byte selector** instead of hardcoding it, so
ERC20 `approve` calls no longer trigger NFT allowance messaging while
NFT-only methods still enable NFT clear signing.
> 
> This adds selector parsing via `@ethersproject/transactions.parse`
(with safe fallback on parse errors), introduces an `NFT_ONLY_SELECTORS`
allowlist, updates unit tests to assert `nft: false/true` behavior for
key selectors and parse failures, and updates LavaMoat policies + deps
to allow direct `@ethersproject/transactions` usage.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
121ed30. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Hassan Malik <41640681+hmalik88@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**

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

This PR introduces the Perps tutorial modal - a 6-step onboarding flow
that educates users about perpetual futures trading. The implementation
matches the design and text from MetaMask Mobile.

Features:
6-step tutorial flow with progress indicator
Rive animations for steps 2-6 with theme support (light/dark)
Static character image for the first step
Responsive layout that works across popup, side panel, and fullscreen
modes
Redux state management for tutorial progress via ducks/perps
Left-aligned text matching mobile design
Skip and Continue navigation with proper state handling

New files:
ui/components/app/perps/perps-tutorial-modal/ - Modal and step
components
ui/ducks/perps/tutorial.ts - Redux slice for tutorial state
ui/ducks/perps/selectors.ts - Redux selectors
app/images/riv_animations/perps-onboarding-carousel-*.riv - Rive
animation files
app/images/perps-character.png - Static character image

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/39693?quickstart=1)

## **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 Perps tutorial modal with animated walkthrough
explaining perpetual futures trading

## **Related issues**

Fixes:

## **Manual testing steps**

Test Steps:
Open the Perps Tutorial Modal
Navigate to the Perps tab
Trigger the tutorial modal (e.g., via "Learn Perps" button)
Test First Step (What Are Perps)
Verify title and description are left-aligned
Verify character image displays correctly
Verify "Continue" and "Skip" buttons are visible
Test Animation Steps (Steps 2-6)
Click Continue to navigate through each step
Verify Rive animations play correctly
Verify animations are not cut off on any edge
Test All Three Viewport Modes:
a) Side Panel Mode (~320px width)
Verify animations display correctly without horizontal cutoff
b) Popup Mode (~360px width)
Verify animations scale appropriately
c) Fullscreen Mode
Verify animations are constrained and not oversized
Test Dark/Light Theme
Switch between dark and light themes
Verify correct animation file loads for each theme
Test Navigation
Verify "Skip" closes the modal
Verify "Continue" progresses to next step
Verify final step completes the tutorial

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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


https://github.com/user-attachments/assets/e66a33f0-d603-4136-a2a4-0eff0c573b58

## **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**
> Adds new Redux state and a modal flow that depends on Rive WASM/asset
loading and environment-specific sizing; regressions would mainly affect
Perps UI onboarding and performance/memory if animation cleanup/loading
fails.
> 
> **Overview**
> Adds a new 6-step Perps tutorial modal (progress indicator +
static/animated visuals) and wires it into `PerpsHomePage` via the
“Learn basics” entry to open the flow.
> 
> Introduces a new `perpsTutorial` Redux slice (open/active
step/completed) with selectors and actions, updates root reducer/state
snapshots, and adds new i18n strings plus component tests (including
Rive animation loading/sizing across popup/sidepanel/fullscreen and
light/dark themes).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ff23a27. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
release: sync stable to main for backport 13.16.4
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Fixes audit failure

<img width="1010" height="203" alt="image"
src="https://github.com/user-attachments/assets/dfdaf402-15b1-495c-9bea-857264cd1cbb"
/>


[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/40133?quickstart=1)

## **Changelog**

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

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

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

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Dependency-only bump limited to `tar` patch-level update with
corresponding lockfile changes; low likelihood of runtime impact beyond
packaging/install behavior.
> 
> **Overview**
> Updates the `tar` dependency resolution from `7.5.7` to `7.5.9` to
address an audit finding.
> 
> Regenerates `yarn.lock` to pin `tar@7.5.9` (updated
resolution/checksum) with no other functional code changes.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
24ddf88. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Fixes three issues we just discovered during the most recent release
cycle:

1. On a changelog branch, like `release/13.19.0-Changelog`, the workflow
ran twice, on both `push` and `pull_request`
   - This was changed to be fixed in MetaMask/github-tools#217
   - Then I simplified `.github/workflows/update-release-changelog.yml`
2. The release branch was not running job `publish-prerelease` because
`needs-benchmarks == 'false'` and the benchmarks were prereqs
3. `prep-e2e` had the gate `if: ${{ (github.head_ref || github.ref_name)
!= 'stable' }}` on the whole job, which prevented it from generating
`test-runs-for-splitting`. Changed to gating just the diff steps.

## **Changelog**

CHANGELOG entry: null

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



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Workflow-only changes to CI/release automation; main risk is
accidentally skipping/triggering release jobs due to updated job
conditions and branch filters.
> 
> **Overview**
> Fixes release-cycle GitHub Actions behavior.
> 
> `publish-prerelease` in `main.yml` is now explicitly gated to run when
releases are enabled and **not cancelled**, requiring all non-benchmark
prerequisite jobs to be `success`/`skipped` so benchmarks no longer
block prereleases.
> 
> `prep-e2e.yml` now runs on `stable`, but skips the diff/artifact steps
there so it still produces `test-runs-for-splitting`.
`publish-prerelease.yml` makes downloading `page-load-benchmark-results`
non-blocking (`continue-on-error`). `update-release-changelog.yml` is
simplified by narrowing the push branch filter to semver-like
`release/x.y.z` and removing the extra branch-validation job.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
95b4e36. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

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

The "Deploy Storybook" workflow still does not work. This workflow is
using a new GitHub app token, *not* a personal access token, to
authenticate the push. When using a GitHub app token, the syntax to
configure a repo URL looks a bit different.

Read more:
<https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation>

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/40073?quickstart=1)

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

No manual testing steps, but I temporarily allowed pull requests to
trigger the workflow. Here is the passing workflow:
https://github.com/MetaMask/metamask-extension/actions/runs/21995079720/job/63552737288

## **Screenshots/Recordings**

(N/A)

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [ ] 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.

[skip-e2e]
<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Small CI-only change that adjusts Git authentication syntax; risk is
limited to the Storybook deployment step failing if misconfigured.
> 
> **Overview**
> Fixes Storybook deployment in CI by updating the `git remote add
storybook` URL to use the `x-access-token:` format required for GitHub
App installation tokens.
> 
> No build logic changes; only the authentication syntax for pushing to
`MetaMask/metamask-storybook` is adjusted.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2fe454f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=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**

When there is no active rewards season, the `RewardsController` throws
errors such as `SeasonNotFoundError` and `"No valid season metadata
could be found for type"`. Previously, these errors were not caught at
the UI/service layer, causing unnecessary error logs and potentially
disrupting the UI for users who don't have an active rewards season.

This PR adds graceful error handling for "season not found" scenarios in
the following places:

- **`useShieldRewards` hook**: Wraps `estimateRewardsPoints` calls in a
try-catch to return `null` points on failure. Catches `"No valid season
metadata could be found for type"` errors from
`getRewardsSeasonMetadata` and returns `isRewardsSeason: false` instead
of surfacing the error.
- **`useSeasonStatus` hook**: Handles `"No valid season metadata could
be found for type"` and `SEASON_NOT_FOUND` errors by clearing season
status and triggering `onAuthorizationError` where appropriate, without
logging noisy errors.
- **`SubscriptionService`**: Catches `"No valid season metadata could be
found for type"` errors in `#getRewardCaipAccountId` and silently
returns `undefined`, downgrading the log level from `warn` to `debug`.

The `RewardsController` itself is intentionally left unchanged — it
continues to throw these errors as expected, and the consuming layers
handle them gracefully.

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/40136?quickstart=1)

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

1. Ensure there is no active rewards season (or simulate by having the
rewards API return no current season).
2. Open the Shield subscription page in MetaMask.
3. Verify no error toasts or error UI is shown — the page loads
gracefully with rewards points displayed as unavailable (null) and
`isRewardsSeason` as `false`.
4. Check the browser console — there should be no error logs related to
"season not found" or "No valid season metadata".
5. When an active rewards season exists, verify that rewards points and
season status load and display correctly as before.

## **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**
> Low risk: narrows error handling to a specific “season metadata not
found” message and adds defensive fallbacks so reward lookups don’t
block Shield subscription flows when no season is active.
> 
> **Overview**
> Suppresses noisy Rewards “season not found” failures across Shield
subscription flows by treating missing current-season metadata as a
non-error state.
> 
> In `SubscriptionService.#getRewardCaipAccountId`, the "No valid season
metadata…" error now short-circuits to `undefined` (skipping opt-in
checks and preventing reward IDs from being attached/linked). In
`useShieldRewards`, rewards points estimation is wrapped to fail closed
with `null` points, and season-metadata lookup maps the same error to
`isRewardsSeason: false` instead of surfacing an exception.
> 
> Adds/extends unit tests to cover these season-not-found scenarios for
both the service and the hook.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
aa08466. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…chmark pipeline (#39587)

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

- Add conditional HTTP mocking for performance benchmarks based on
branch context:
- Mock requests for normal PRs (feature branches) - faster, reliable CI
- Real server requests for `main` branch and release branches
- Add webpack build for performance benchmarks for `main` branch and
release branches

#### Performance Mocks - Request Timing Chart (30-day Sentry Data)

| # | Endpoint | Method | Mock Delay (ms) | Sentry p50 (ms) | Sentry
Link |

|---|----------|--------|-----------------|-----------------|-------------|
| **Analytics & Monitoring** |||||
| 1 | sentry.io | POST | 100 | N/A (outbound) | - |
| 2 | segment.io | POST | 100 | N/A (outbound) | - |
| **Authentication & Identity** |||||
| 3 | authentication.api.cx.metamask.io (nonce) | GET | 1200 | ~1196 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*authentication.api.cx.metamask.io*&project=273505&statsPeriod=30d&table=span)
|
| 4 | authentication.api.cx.metamask.io (login) | POST | 1200 | ~1196 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*authentication.api.cx.metamask.io*&project=273505&statsPeriod=30d&table=span)
|
| 5 | oidc.api.cx.metamask.io (token) | POST | 3400 | ~3383 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*oidc.api.cx.metamask.io*&project=273505&statsPeriod=30d&table=span)
|
| 6 | user-storage.api.cx.metamask.io | GET | 500 | ~463 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*user-storage.api.cx.metamask.io*&project=273505&statsPeriod=30d&table=span)
|
| 7 | user-storage.api.cx.metamask.io | PUT | 500 | ~463 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*user-storage.api.cx.metamask.io*&project=273505&statsPeriod=30d&table=span)
|
| **MetaMask APIs** |||||
| 8 | token.api.cx.metamask.io/tokens | GET | 800 | ~800 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*token.api*tokens*&project=273505&statsPeriod=30d&table=span)
|
| 9 | defiadapters.api.cx.metamask.io/positions | GET | 1000 | ~1000 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*defiadapters*&project=273505&statsPeriod=30d&table=span)
|
| 10 | on-ramp-content.api.cx.metamask.io | GET | 1200 | ~1200 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*on-ramp-content*&project=273505&statsPeriod=30d&table=span)
|
| 11 | accounts.api.cx.metamask.io/.../surveys | GET | 7000 | ~7000 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*accounts.api*surveys*&project=273505&statsPeriod=30d&table=span)
|
| 12 | accounts.api.cx.metamask.io/.../transactions | GET | 5000 | ~5000
|
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*accounts.api*transactions*&project=273505&statsPeriod=30d&table=span)
|
| 13 | accounts.api.cx.metamask.io/.../balances | GET | 5000 | ~5000 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*accounts.api*balances*&project=273505&statsPeriod=30d&table=span)
|
| 14 | phishing-detection.api.cx.metamask.io | GET | 5000 | ~5000 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*phishing-detection*&project=273505&statsPeriod=30d&table=span)
|
| 15 | client-side-detection.api.cx.metamask.io | GET | 6000 | ~6000 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*client-side-detection*&project=273505&statsPeriod=30d&table=span)
|
| 16 | subscription.api.cx.metamask.io/subscriptions | GET | 3000 |
~3000 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*subscription*&project=273505&statsPeriod=30d&table=span)
|
| 17 | subscription.api.cx.metamask.io/.../eligibility | GET | 3000 |
~3000 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*subscription*eligibility*&project=273505&statsPeriod=30d&table=span)
|
| 18 | client-config.api.cx.metamask.io/v1/flags | GET | 1000 | ~1000 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*client-config*flags*&project=273505&statsPeriod=30d&table=span)
|
| 19 | security-alerts.api.cx.metamask.io | POST | 1000 | ~1000 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*security-alerts*&project=273505&statsPeriod=30d&table=span)
|
| 20 | static.cx.metamask.io (icons) | GET | 200 | ~200 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*static.cx.metamask*&project=273505&statsPeriod=30d&table=span)
|
| 21 | chainid.network/chains.json | GET | 1200 | ~1200 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*chainid.network*&project=273505&statsPeriod=30d&table=span)
|
| 22 | accounts.google.com | ANY | 100 | N/A | - |
| 23 | metamask.github.io/ledger-iframe-bridge | GET | 100 | N/A | - |
| 24 | app.ens.domains | GET | 100 | N/A | - |
| 25 | trigger.api.cx.metamask.io | ANY | 100 | N/A | - |
| 26 | notification.api.cx.metamask.io | ANY | 100 | N/A | - |
| 27 | content.api.cx.metamask.io | GET | 100 | N/A | - |
| **Price APIs** |||||
| 28 | price.api.cx.metamask.io/.../supportedVsCurrencies | GET | 500 |
~500 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*supportedVsCurrencies*&project=273505&statsPeriod=30d&table=span)
|
| 29 | price.api.cx.metamask.io/.../supportedNetworks | GET | 500 | ~500
|
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*supportedNetworks*&project=273505&statsPeriod=30d&table=span)
|
| 30 | price.api.cx.metamask.io/.../exchange-rates/fiat | GET | 100 |
~100 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*exchange-rates*&project=273505&statsPeriod=30d&table=span)
|
| 31 | price.api.cx.metamask.io/.../exchange-rates | GET | 100 | ~100 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*exchange-rates*&project=273505&statsPeriod=30d&table=span)
|
| 32 | price.api.cx.metamask.io/.../spot-prices/bitcoin | GET | 2000 |
~2000 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*spot-prices*bitcoin*&project=273505&statsPeriod=30d&table=span)
|
| 33 | price.api.cx.metamask.io/.../spot-prices/solana | GET | 2000 |
~2000 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*spot-prices*solana*&project=273505&statsPeriod=30d&table=span)
|
| 34 | price.api.cx.metamask.io/.../spot-prices (query-solana) | GET |
2000 | ~2000 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*spot-prices*&project=273505&statsPeriod=30d&table=span)
|
| 35 | price.api.cx.metamask.io/.../spot-prices (general) | GET | 2000 |
~2000 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*spot-prices*&project=273505&statsPeriod=30d&table=span)
|
| 36 | price.api.cx.metamask.io/.../historical-prices (EVM) | GET | 600
| ~568 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*historical-prices*&project=273505&statsPeriod=30d&table=span)
|
| 37 | price.api.cx.metamask.io/.../historical-prices (non-EVM) | GET |
600 | ~568 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*historical-prices*&project=273505&statsPeriod=30d&table=span)
|
| 38 | min-api.cryptocompare.com/data/pricemulti | GET | 1300 | ~1299 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*cryptocompare*&project=273505&statsPeriod=30d&table=span)
|
| 39 | min-api.cryptocompare.com/data/price | GET | 1300 | ~1299 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*cryptocompare*&project=273505&statsPeriod=30d&table=span)
|
| **Gas APIs** |||||
| 40 | gas.api.cx.metamask.io/.../suggestedGasFees | GET | 500 | ~500 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*suggestedGasFees*&project=273505&statsPeriod=30d&table=span)
|
| 41 | gas.api.cx.metamask.io/.../gasPrices | GET | 600 | ~600 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*gasPrices*&project=273505&statsPeriod=30d&table=span)
|
| **Bridge APIs** |||||
| 42 | bridge.api - getTokens/popular | POST | 300 | ~300 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*getTokens*popular*&project=273505&statsPeriod=30d&table=span)
|
| 43 | bridge.api - getTokens/search | POST | 300 | ~300 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*getTokens*search*&project=273505&statsPeriod=30d&table=span)
|
| 44 | bridge.api - getTokens | GET | 300 | ~300 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*bridge*getTokens*&project=273505&statsPeriod=30d&table=span)
|
| 45 | bridge.api - networks/*/tokens | GET | 300 | ~300 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*bridge*tokens*&project=273505&statsPeriod=30d&table=span)
|
| 46 | bridge.api - getQuote | GET | 2000 | ~2000 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*getQuote*&project=273505&statsPeriod=30d&table=span)
|
| 47 | bridge.api - getQuoteStream (SSE) | GET | 2000 | ~15000-25000 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*getQuoteStream*&project=273505&statsPeriod=30d&table=span)
|
| 48 | bridge.api - getAllFeatureFlags | GET | 1500 | ~1500 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*getAllFeatureFlags*&project=273505&statsPeriod=30d&table=span)
|
| 49 | bridge.api - catch-all | GET | 500 | ~500 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*bridge.api*&project=273505&statsPeriod=30d&table=span)
|
| 50 | topAssets | GET | 400 | ~400 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*topAssets*&project=273505&statsPeriod=30d&table=span)
|
| 51 | aggregatorMetadata | GET | 500 | ~500 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*aggregatorMetadata*&project=273505&statsPeriod=30d&table=span)
|
| **Infura RPC (EVM)** |||||
| 52 | mainnet.infura.io | POST | 1800 | p50: ~300, p95: ~1300 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*mainnet.infura*&project=273505&statsPeriod=30d&table=span)
|
| 53 | polygon-mainnet.infura.io | POST | 1400 | ~1400 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*polygon-mainnet.infura*&project=273505&statsPeriod=30d&table=span)
|
| 54 | bsc-mainnet.infura.io | POST | 1500 | ~1500 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*bsc-mainnet.infura*&project=273505&statsPeriod=30d&table=span)
|
| 55 | optimism-mainnet.infura.io | POST | 1500 | ~1500 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*optimism-mainnet.infura*&project=273505&statsPeriod=30d&table=span)
|
| 56 | arbitrum-mainnet.infura.io | POST | 1500 | ~1500 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*arbitrum-mainnet.infura*&project=273505&statsPeriod=30d&table=span)
|
| 57 | base-mainnet.infura.io | POST | 1300 | p50: ~300, p95: ~1300 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*base-mainnet.infura*&project=273505&statsPeriod=30d&table=span)
|
| 58 | linea-mainnet.infura.io | POST | 1300 | p50: ~300, p75: ~700,
p95: ~1300 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*linea-mainnet.infura*&project=273505&statsPeriod=30d&table=span)
|
| 59 | avalanche-mainnet.infura.io | POST | 900 | ~900 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*avalanche-mainnet.infura*&project=273505&statsPeriod=30d&table=span)
|
| 60 | sepolia.infura.io | POST | 500 | ~500 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*sepolia.infura*&project=273505&statsPeriod=30d&table=span)
|
| 61 | linea-sepolia.infura.io | POST | 500 | ~500 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*linea-sepolia.infura*&project=273505&statsPeriod=30d&table=span)
|
| 62 | celo-mainnet.infura.io | POST | 1500 | ~1500 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*celo-mainnet.infura*&project=273505&statsPeriod=30d&table=span)
|
| **Other EVM RPC** |||||
| 63 | rpc.gnosischain.com | POST | 1500 | ~1500 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*gnosischain*&project=273505&statsPeriod=30d&table=span)
|
| 64 | mainnet.era.zksync.io | POST | 900 | ~916 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*era.zksync*&project=273505&statsPeriod=30d&table=span)
|
| 65 | carrot.megaeth.com | POST | 100 | N/A (testnet) | - |
| 66 | testnet-rpc.monad.xyz | POST | 100 | N/A (testnet) | - |
| **Solana RPC** |||||
| 67 | solana-mainnet.infura.io - getBalance | POST | 100 | p50: ~55,
p75: ~100 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*solana*&project=273505&statsPeriod=30d&table=span)
|
| 68 | solana-mainnet.infura.io - getAccountInfo | POST | 100 | p50:
~55, p75: ~100 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*solana*&project=273505&statsPeriod=30d&table=span)
|
| 69 | solana-mainnet.infura.io - getLatestBlockhash | POST | 100 | p50:
~55, p75: ~100 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*solana*&project=273505&statsPeriod=30d&table=span)
|
| 70 | solana-mainnet.infura.io - getFeeForMessage | POST | 100 | p50:
~55, p75: ~100 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*solana*&project=273505&statsPeriod=30d&table=span)
|
| 71 | solana-mainnet.infura.io - getMinimumBalanceForRentExemption |
POST | 100 | p50: ~55, p75: ~100 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*solana*&project=273505&statsPeriod=30d&table=span)
|
| 72 | solana-mainnet.infura.io - getTokenAccountsByOwner | POST | 100 |
p50: ~55, p75: ~100 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*solana*&project=273505&statsPeriod=30d&table=span)
|
| 73 | solana-mainnet.infura.io - simulateTransaction | POST | 100 |
p50: ~55, p75: ~100 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*solana*&project=273505&statsPeriod=30d&table=span)
|
| 74 | solana-mainnet.infura.io - getSignaturesForAddress | POST | 100 |
p50: ~55, p75: ~100 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*solana*&project=273505&statsPeriod=30d&table=span)
|
| 75 | solana-mainnet.infura.io - catch-all | POST | 1500 | p50: ~55,
p75: ~100 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*solana*&project=273505&statsPeriod=30d&table=span)
|
| **Other** |||||
| 76 | acl.execution.metamask.io/registry.json | GET | 500 | ~500 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*acl.execution*&project=273505&statsPeriod=30d&table=span)
|
| 77 | acl.execution.metamask.io/signature.json | GET | 500 | ~500 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*acl.execution*&project=273505&statsPeriod=30d&table=span)
|
| 78 | portfolio.metamask.io | GET | 800 | ~800 |
[View](https://metamask.sentry.io/explore/traces/?query=span.op%3Ahttp.client+AND+span.description%3A*portfolio.metamask*&project=273505&statsPeriod=30d&table=span)
|

### Notes
- *Row 39 (getQuoteStream): Mock delay set to 400ms for test
compatibility with UI assertions, though Sentry shows 15-25s actual
duration.
- Authentication endpoints (#3-7) were added with Sentry-verified
delays.
- User storage delay was reduced from 6000ms to 500ms based on actual
Sentry data (463ms avg).


[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/39587?quickstart=1)

## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Fixes: MetaMask/MetaMask-planning#6832;
MetaMask/MetaMask-planning#6833

## **Manual testing steps**

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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




<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches CI workflow orchestration and benchmark
network-mocking/pass-through behavior, which can subtly change what
benchmarks measure and when jobs run, but is contained to E2E
benchmarking infrastructure.
> 
> **Overview**
> Performance benchmark runs now **switch between full HTTP mocking
(PR/feature branches) and real network pass-through (pushes to
`main`/`release/*`)** via a new `mock-config.ts` helper and a large
`performance-mocks` suite (prices, bridge/swap, auth, RPCs, etc.) with
realistic delays.
> 
> The benchmarks workflow is updated to set `GITHUB_REF_NAME` for this
decision and to add a separate `benchmarks-webpack-perf` job
(main/release pushes only) to collect Chrome+Webpack performance results
alongside the existing Chrome+Browserify performance runs.
> 
> Additional benchmark plumbing changes include a pass-through
interceptor mechanism for selectively mocking requests when using HTTPS
pass-through (used by swap), more robust “empty results” handling in
`send-to-sentry.ts`, updated thresholds for asset-details, extra request
logging, allowlist additions (`celo-mainnet.infura.io`,
`rpc.gnosischain.com`), and removal of legacy
`user-actions-benchmark.ts` and `common-mocks.ts`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ca07006. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=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**

Remove advanced setting - Use smart account.

## **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: MetaMask/MetaMask-planning#6991

## **Manual testing steps**
NA

## **Screenshots/Recordings**
TODO

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> UI/settings cleanup only; removes a toggle and related copy/tests
without changing core transaction or account logic.
> 
> **Overview**
> Removes the **Advanced Settings** opt-in control for "Use smart
account" from the `AdvancedTab` UI, including the learn-more link and
toggle handling.
> 
> Cleans up related wiring by dropping the `smartAccountOptIn` prop and
`setSmartAccountOptIn` dispatch from the settings container, updating
the advanced tab snapshot/unit tests (checkbox index shifts), and
deleting the associated i18n strings across locales.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
cc40059. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=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 is to update hamburger to use global-menu drawer instead of
global-menu popover component.
Note: This PR also removed the headless-ui library and implemented the
drawer from scratch. Hence, the changes in `package.json`. It's not
impacted other files because we added that library only for drawer
component

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/39991?quickstart=1)

## **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: replaced global-menu with global-menu-drawer

## **Related issues**

Fixes:
[issue](https://consensyssoftware.atlassian.net/browse/CEUX-864?atlOrigin=eyJpIjoiNDEzZTVlNGQ5NzU3NDdlMThmMGExY2EzMzA3YThmMTciLCJwIjoiaiJ9)

## **Manual testing steps**

1. Run extension with yarn start
2. click on hamburger menu. See the drawer appears
3. Click on the snaps or any other route menu, it should navigate to the
page
4. Click on the back button on Page, it should redirect to homepage with
the drawer open (drawer should have transition)

## **Screenshots/Recordings**

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

### **Before**

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

### **After**





https://github.com/user-attachments/assets/234f488e-a1d2-49da-aa28-b59a0f8fb686



## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches core navigation and the global header menu/drawer behavior,
including custom transition/portal logic and new URL-driven state, which
could introduce regressions in routing or overlay interactions across
environments.
> 
> **Overview**
> Replaces the header hamburger `GlobalMenu` popover with
`GlobalMenuDrawerWithList`, and persists the drawer open/close state via
a `drawerOpen` URL search param to avoid close/reopen flashes across
route changes.
> 
> Refactors `GlobalMenuDrawer` to drop `@headlessui/react` in favor of a
custom, phase-based transition implementation, with updated
portal/positioning logic for fullscreen and sidepanel environments plus
Escape/outside-click closing.
> 
> Updates global menu navigation to carry a `from` query param into
`Notifications`, `Snaps`, and permissions routes and adjusts back-button
behavior in `notifications`, `snap-list`, `permissions-page`, and
`gator-permissions-page` accordingly; menu list styling/testids were
tweaked, unit/e2e tests updated/added, and `@headlessui/react` was
removed from dependencies.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a0a8a2c. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
…#40107)

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

This PR is part of a series to remove the legacy code after BIP-44 was
shipped, several components, hooks, views, etc. still uses the remote
feature flag for BIP-44 causing an unnecessary overcomplexity that can
be easily removed.

The changes include updating the component `SnapUIAvatar` and the hook
`useDisplayName`.

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/40107?quickstart=1)

## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MUL-1454

## **Manual testing steps**

Not applicable

## **Screenshots/Recordings**

Not applicable

### **Before**

Not applicable

## **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 refactor removing a feature-flag branch; behavior only changes
in cases where account-group data exists but the flag was previously
off.
> 
> **Overview**
> `SnapUIAvatar` no longer checks
`getIsMultichainAccountsState2Enabled`; it always uses the first EVM
account in the resolved account group (if present) as the avatar address
fallback instead of gating on a feature flag.
> 
> `useDisplayName` similarly drops the feature-flag condition and always
prefers `accountGroupName` ahead of per-account names/address-book
entries when an account group is found.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0cd07ee. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

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

This PR is part of a series to remove the legacy code after BIP-44 was
shipped, several components, hooks, views, etc. still uses the remote
feature flag for BIP-44 causing an unnecessary overcomplexity that can
be easily removed.

The changes included updating the components relevant for the "Wallet
Overview".

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/40029?quickstart=1)

## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MUL-1451

## **Manual testing steps**

Not applicable

## **Screenshots/Recordings**

Not applicable

## **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 user-facing wallet overview rendering and receive/chain-switch
preconditions by removing a gating feature flag, which could expose edge
cases for accounts without a valid `selectedAccountGroup` or incomplete
account-tree state.
> 
> **Overview**
> Wallet Overview no longer branches on the BIP-44/multichain state2
feature flag: `CoinOverview` always renders `AccountGroupBalance` and
`AccountGroupBalanceChange`, and `AccountGroupBalanceChange` no longer
returns `null` when the flag is off.
> 
> `CoinButtons` and the balance-empty-state receive handler now route to
the multichain address list whenever `selectedAccountGroup` exists (and
chain-switching no longer depends on the flag), simplifying behavior and
removing legacy paths. Tests were updated accordingly (new `accountTree`
fixtures, formatting expectations like `0.0104 ETH`, and removal of
flag-disabled assertions).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
5422b6d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…0032)

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

This PR is part of a series to remove the legacy code after BIP-44 was
shipped, several components, hooks, views, etc. still uses the remote
feature flag for BIP-44 causing an unnecessary overcomplexity that can
be easily removed.

The changes included updating the components relevant for the Accounts
and Networks.

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/40032?quickstart=1)

## **Changelog**

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

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

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

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MUL-1453

## **Manual testing steps**

Not applicable

## **Screenshots/Recordings**

Not applicable

## **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**
> Removes feature-flag gating and legacy fallbacks across core home
header/activity and network selection flows, which could subtly change
what users see/can click. Risk is mitigated by being primarily
conditional-removal/refactor with updated unit tests.
> 
> **Overview**
> This PR removes the BIP-44 / multichain “state2” feature-flag
branching from several account and network UI components, making the
multichain implementations the only code path.
> 
> Notable behavior changes include always rendering
`UnifiedTransactionList` in the home Activity tab, simplifying the
unlocked header to the multichain account picker (and dropping the
legacy address copy button/tour path), removing conditional styling
logic in `AccountPicker`, and simplifying connection status/permissions
list account counting to rely solely on multichain account groups.
> 
> In network manager, default networks filtering is refactored to use
account-group presence (EVM/Solana/Bitcoin/Tron) and “basic
functionality” toggles without the old flag gates, and UI sections like
“All popular networks” and additional networks are now shown
unconditionally. Tests for `ConnectionListItem` are updated to remove
flag-based expectations.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2bd256e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Various libraries have been updated in preparation for ESLint v9. These
are all in-range updates, lockfile-only.

The `eslint-plugin-import` update uncovered a few new lint errors, which
have all been fixed.

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/39990?quickstart=1)

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Primarily dependency/policy updates plus a mechanical export change
for deep-link routes; low behavioral risk but may affect builds/linting
if any import paths were missed.
> 
> **Overview**
> Updates ESLint-related dependencies (e.g., `eslint-plugin-import`,
`@typescript-eslint/*`, resolver utilities) and refreshes `yarn.lock`,
including new transitive packages.
> 
> Adjusts LavaMoat policies (`lavamoat/build-system/policy.json`,
`lavamoat/webpack/build/policy.json`) to match the updated dependency
graph.
> 
> Fixes newly surfaced lint/type issues by consolidating `Json`/`Hex`
type imports in `metametrics-controller.ts` and refactoring deep-link
route modules to use named exports (`export const ...`) instead of
default exports, updating `routes/index.ts` and associated tests
accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
185d255. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 22, 2026

Builds ready [e453d6b]

@metamaskbot metamaskbot added the release-13.20.0 Issue or pull request that will be included in release 13.20.0 label Feb 23, 2026
….20.0 (#40328)

- chore: Resolve multiple advisories (#40320)

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

Resolve GHSA-2g4f-4pwh-qvx6 partly by
bumping `addons-linter`, `ajv` and by modifying the ignored advisory.
The dependency is only used for dev.

Resolve GHSA-378v-28hj-76wf by bumping
`bn.js`.

Partially resolve GHSA-3ppc-4f35-3m26 by
bumping `minimatch`, it was partially resolved by ignoring in the first
place.

This should get main passing.

[![Open in GitHub

Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/40320?quickstart=1)

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Lockfile/config-only changes to dev/build-time dependencies; low
runtime impact, but CI/build behavior could change if tooling relies on
exact versions.
> 
> **Overview**
> Updates the Yarn audit ignore list by replacing the ignored
`minimatch` advisory ID (`1113296` -> `1113371`).
> 
> Refreshes dependency metadata/locks to resolve advisories, including
bumps to `addons-linter` (9.6.0 -> 9.8.0) and related transitive deps
(`addons-scanner-utils`, `@mdn/browser-compat-data`, `ajv` 8.x), plus
security-motivated updates to `ajv` 6.x (6.12.6 -> 6.14.0), `bn.js`
(5.2.1 -> 5.2.3), and `minimatch` (10.1.1 -> 10.2.2, with updated
`brace-expansion`/`balanced-match` entries). `attribution.txt` is
updated to reflect the new `ajv` and `bn.js` versions.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
02a509a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->


[64b4472](64b4472)

---------

Co-authored-by: Frederik Bolding <frederik.bolding@gmail.com>
Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 23, 2026

Builds ready [7519e5a]

…o drawer (#40326)

- feat: cp-13.20.0 added vertical scroll to drawer (#40301)

This PR is to add vertical scroll to drawer 

## **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: adds vertical scroll to drawer

## **Related issues**

Fixes:

## **Manual testing steps**

1. Go to small window size for full screen
2. check drawer is scrollable

## **Screenshots/Recordings**

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

### **Before**

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

### **After**



https://github.com/user-attachments/assets/05057dc9-feec-4742-8460-da12c21436d1



## **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**
> CSS/layout-only changes scoped to the global menu drawer; main risk is
minor visual regressions across fullscreen/sidepanel breakpoints.
> 
> **Overview**
> Adjusts `GlobalMenuDrawer` layout/styling to support reliable vertical
scrolling and proper sizing in fullscreen vs sidepanel.
> 
> This refines fullscreen top offset handling (explicit 90px logo
offset), ensures the drawer panel always spans `top`/`bottom`, and adds
`min-h-0`, `flex-shrink-0`, and bottom padding so the header stays fixed
while the content area scrolls correctly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9d2b59a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->


[cb1f3f9](cb1f3f9)

Co-authored-by: Nidhi Kumari <nidhi.kumari@consensys.net>
Co-authored-by: chloeYue <105063779+chloeYue@users.noreply.github.com>
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 23, 2026

Builds ready [e39efa5]

…40335)

- fix: align date year format cp-13.20.0 (#40329)

CHANGELOG entry: fix: activity year format
…e cp-13.20.0 (#40334)

- fix: list item disappearing in token page cp-13.20.0 (#40316)

CHANGELOG entry: fix: list item disappearing in token page
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 23, 2026

Builds ready [d656234]

…fully in token import flow for custom network cp-13.20.0 (#40347)

- fix: handle evm unsupported chains gracefully in token import flow for
custom network cp-13.20.0 (#40325)

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

## **Description**

Fixes error when importing tokens on EVM networks with decimal string
chainIds (e.g., Injective testnet) using similar strategy to:
#39806.

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

[![Open in GitHub

Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/40325?quickstart=1)

## **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 error when importing tokens on EVM networks when
chainId is provided as decimal string.

## **Related issues**

Related to PR: #39806

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




https://github.com/user-attachments/assets/edb9f332-9d5e-46f4-b04d-528c264f66aa



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

### **After**



https://github.com/user-attachments/assets/f8da6e12-12f8-4034-a98e-37ac67a1a436


<!-- [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 defensive UI-hook change that only affects native token
image/metadata resolution; primary risk is minor regressions in icon
fallback behavior for edge-case chains.
> 
> **Overview**
> Hardens `useTokensWithFiltering` when yielding native assets from
multichain balances by using `getNativeAssetForChainIdSafe` and by
guarding `getAssetImageUrl` behind a try/catch.
> 
> This prevents token list generation from throwing on
unsupported/custom EVM networks (e.g., decimal-string chainIds), while
keeping the existing image fallback order (chain image maps → native
asset icon/iconUrl → derived asset image URL).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d796471. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->


[9fcbdfe](9fcbdfe)

Co-authored-by: khanti42 <florin.dzeladini@consensys.net>
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 24, 2026

Builds ready [2c1a759]

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 24, 2026

Builds ready [5682c55]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.