Repository navigation
release: 13.51.0 - #46634
release: 13.51.0#46634
Conversation
<!-- 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** Video about how to change API endpoint: https://www.loom.com/share/3cbc2fda74454e809ad64bfbea116c7d <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] 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 how authenticated core-backend clients are configured for assets/DeFi flows; mis-set env vars could point wallets at wrong backends or omit auth in production builds. > > **Overview** > Adds **build-time env overrides** for core-backend REST services (accounts, prices, token/tokens APIs) via `shared/lib/core-backend-api-urls`, documented in `.metamaskrc.dist` and wired through `builds.yml`. > > **Assets** and **DeFi positions v2** init now spread `getBackendApiUrlsOption()` into `createApiPlatformClient` and skip `AuthenticationController:getBearerToken` when `MM_BACKEND_DISABLE_AUTH=true`, so dev/local backends that reject production tokens can be used with the URL overrides. > > Includes a unit test for the disabled-auth path in assets init and **LavaMoat webpack policy** updates (scoped dependency entries) aligned with the dependency graph. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 91f9c62. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com> Co-authored-by: Prithpal Sooriya <prithpal.sooriya@gmail.com> Co-authored-by: Davide Brocchetto <davide.brocchetto@consensys.net> Co-authored-by: Prithpal Sooriya <prithpal.sooriya@consensys.net> Co-authored-by: Cursor <cursoragent@cursor.com>
…issing (#46420) <!-- 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? --> When Accounts API `valueTransfers[].decimal` is missing, Activity scaled raw base-unit amounts with `decimals ?? 0` — e.g. a 167.1211 USDT send rendered as `-167.12M` with fiat from the same unscaled number. Map-time fail-closed / `getKnownTokenDecimals` landed in core ([#10256](MetaMask/core#10256)) but is not published yet; Extension is still on `@metamask/client-utils@2.0.2`. This PR is a **minimal display-layer safety net** only (parity with [Mobile #36406](MetaMask/metamask-mobile#36406); no temporary recovery to remove later): 1. `getHumanReadableTokenAmount` returns `undefined` for EVM mapper amounts (`assetType: 'erc20' | 'native'`) with unknown decimals — amount and derived fiat are omitted instead of inflated. 2. When amount is omitted **and** scale is unknown (`hasUnknownScale`), returns `undefined` instead of inventing `'0'`, so fail-closed mapper rows do not show fake zero transfers. Zero-value natives that omit amount but keep known decimals (and `assetType` since client-utils 1.3.0) still render as `0` / `-0 ETH`. Ramp / keyring human-readable amounts (no `assetType`) are unchanged. Zero-value native metadata-only rows without `assetType` still render as `0`. **Follow-up after client-utils publish + Extension bump:** wire optional `getKnownTokenDecimals` at mapper call sites for recovery. This display guard can stay as belt-and-suspenders. ## **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 Activity showing hugely inflated token and fiat amounts when transfer decimals were missing ## **Related issues** Fixes: [TMCU-1303](https://consensyssoftware.atlassian.net/browse/TMCU-1303) ## **Manual testing steps** 1. Build and load the extension (`yarn start`) with Activity Redesign enabled. 2. Send an ERC-20 whose Accounts API payload includes `decimal` enrichment; open Activity list and details; verify human-readable amount and fiat render correctly. 3. Reproduce or fixture a transfer whose payload omits `decimal` (or inspect a known missing-decimals capture); open Activity list/details for that transfer. 4. Verify the amount is blank (not inflated like `167.12M`, not fake `0`), and fiat is not computed from unscaled base units. 5. Confirm a recent ramp buy/sell and a Solana/non-EVM transfer still show human-readable amounts. 6. Confirm a zero-value contract interaction / send (amount omitted, decimals known, including with `assetType: 'native'`) still shows `0` / `-0 ETH`. ## **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. [TMCU-1303]: https://consensyssoftware.atlassian.net/browse/TMCU-1303?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Display-only guard in Activity amount formatting with targeted EVM `assetType` checks; intentional blank amounts replace incorrect inflated or zero values. > > **Overview** > Activity was treating missing `decimals` as **0** for EVM-mapped transfers (`assetType: 'erc20' | 'native'`), so raw base-unit values showed up as huge token amounts and drove inflated fiat. > > **`getHumanReadableTokenAmount`** now **returns `undefined`** when EVM mapper tokens have unknown scale (no `decimals` with `assetType`), and when the amount is missing but `assetType` is set—so the UI omits the amount/fiat instead of showing inflated numbers or a fake **`0`**. Ramp/keyring rows without `assetType` still pass through human-readable values; legacy zero-value native rows without `assetType` still render as **`0`**. > > Tests cover fail-closed omission, unknown-decimals EVM amounts, and unchanged non-EVM/human-readable paths. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 81227ba. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…ings (#46443) ## Summary Fix for [#46453](#46453) - Slippage values above 100% are meaningless in DeFi — 100% already means "accept any price, including receiving nothing". Allowing values above this threshold could confuse users or silently mask bugs in downstream price calculations. - The Bridge transaction settings modal (`bridge-transaction-settings-modal.tsx`) now clamps the input value to `'100'` on every keystroke and applies a `Math.min(newSlippage, 100)` guard on submit. - The Swaps transaction settings (`transaction-settings.js`) applies the same clamp on the `onChange` handler. - A new E2E test (`swaps-notifications.spec.ts`) verifies that entering `101` results in `100` being displayed and used. Before: https://www.loom.com/share/25b31e0c7eca4fcebf7389bd3971b0e7 Now: https://www.loom.com/share/3ad5ef977862456c80c4e59ad7a5ad7e ## Changes | File | Change | |------|--------| | `ui/pages/bridge/prepare/bridge-transaction-settings-modal.tsx` | Clamp input to 100 on change + Math.min guard on submit | | `ui/pages/swaps/transaction-settings/transaction-settings.js` | Clamp input to 100 on change | | `test/e2e/page-objects/pages/bridge/quote-page.ts` | Add `checkCustomSlippageDisplayedValue` helper + `submitSlippageModal` | | `test/e2e/tests/swaps/swaps-notifications.spec.ts` | Add E2E test asserting 101 is clamped to 100 | ## Test plan - [ ] Open Bridge flow → Transaction Settings → enter `101` as custom slippage → confirm the field shows `100` - [ ] Open Swaps flow → Transaction Settings → enter `101` as custom slippage → confirm the field shows `100` - [ ] Run the new E2E test: `yarn test:e2e --grep "clamps slippage to 100"` - [ ] Verify entering `99` or `0.5` still works correctly (no unintended clamping) - [ ] Verify existing slippage warning tests still pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes slippage validation and Redux error-key behavior in swap/bridge flows, which can affect whether quotes proceed, though the cap aligns with existing max-tolerance semantics. > > **Overview** > Custom slippage above **100%** is now treated as invalid for both **Bridge** and **Swaps** transaction settings, since higher values do not change meaning and can mislead users or downstream quote logic. > > In the **Bridge** settings modal, blur on the custom field applies `Math.min(..., 100)`, updates the custom control to **100%**, and shows a warning using the new **`swapSlippageCappedDescription`** copy. The custom input also gets **`inputmode="decimal"`**. > > **Swaps** settings cap on blur/Enter via **`finishEnteringCustomValue`**, set **`isSlippageCapped`**, and surface the same capped message (with existing over-limit title) while keeping other low/high/negative warnings in a extracted **`getSlippageNotification`** helper. Preset buttons clear the capped state; error-key dispatch is driven off that helper. > > Coverage adds locale strings, bridge/swaps unit expectations, bridge page-object helpers, and an E2E case that entering **101** displays **100%**. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 1f7b422. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: javiergarciavera <javiergarciavera@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? --> After a conversation between Networks, DataLake and API teams, the fix is moved to the backed side (basically the WS publishes the updates for the slip44 USDC representation on Arc instead of the ERC20 one). This PR reverts the changes in #46259 not needed anymore ## **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 forced fetch for Arc assets ## **Related issues** Fixes: [WPN-2105](https://consensyssoftware.atlassian.net/browse/WPN-2105) ## **Manual testing steps** ### Arc swaps 1. On Arc, confirm the starting balances for EURC and native USDC. 2. Swap EURC -> USDC. 3. After the transaction is confirmed, verify: - EURC decreased. - native USDC increased. - the USDC balance shown in the wallet matches the expected post-swap balance. 4. Swap USDC -> EURC. 5. After the transaction is confirmed, verify: - native USDC decreased. - EURC increased. - both balances update automatically from the confirmed transaction/WebSocket update. ### Ethereum swaps 1. On Ethereum, confirm the starting balances for ETH and USDC. 2. Swap ETH -> USDC. 3. After confirmation, verify: - ETH decreased, including gas. - USDC increased. 4. Swap USDC -> ETH. 5. After confirmation, verify: - USDC decreased. - ETH increased, accounting for gas. 6. Pick any ERC20 token supported by the swap flow. 7. Swap that ERC20 token -> USDC. 8. After confirmation, verify: - the ERC20 token decreased. - USDC increased. 9. Swap USDC -> the same ERC20 token. 10. After confirmation, verify: - USDC decreased. - the ERC20 token increased. ### Bridge 1. Confirm the starting USDC balances on Ethereum and Arc. 2. Bridge USDC.ETH -> USDC.ARC. 3. After the bridge completes, verify: - Ethereum USDC decreased. - Arc native USDC increased. - Arc USDC updates automatically in the wallet. 4. Bridge USDC.ARC -> USDC.ETH. 5. After the bridge completes, verify: - Arc native USDC decreased. - Ethereum USDC increased. - both network balances match the expected post-bridge state. ### Regression check 1. Repeat at least one Arc swap while DevTools is open. 2. Verify there is no extension-side forced asset refresh triggered from `TransactionController:transactionConfirmed`. 3. Verify the Arc native USDC balance still updates correctly after confirmation. ## **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** - [X] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [X] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Removes a client-side recovery path for stale Arc native USDC balances; correctness now depends on backend WS updates being in place and reliable. > > **Overview** > Reverts the extension-side workaround that listened for **`TransactionController:transactionConfirmed`** on Arc and triggered a forced **`getAssets`** refresh (with **`forceUpdate`** and **`bypassServerCache`**) for the sending account in the selected group. > > That logic lived in **`assets-controller-init.ts`** as **`subscribeToArcTransactionConfirmedRefresh`** and is removed along with its Arc-specific imports and constants. **`AssetsControllerInit`** no longer registers that subscriber after controller creation. > > The matching unit tests in **`assets-controller-init.test.ts`** (including the **`getAssets`** mock) are deleted so init tests no longer cover Arc confirmation-driven refreshes. > > Arc native USDC balance updates after swaps/bridges are expected to come from backend/WebSocket (slip44 USDC) instead of this client fetch. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 59f4f41. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> [WPN-2105]: https://consensyssoftware.atlassian.net/browse/WPN-2105?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Migrates MetaMetrics persistence, traces, and unlock-wallet E2E specs to Playwright. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MMQA-2259 ## **Manual testing steps** CI should be green ## **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** > Changes are limited to E2E harness proxy wiring and test migrations; no production analytics behavior is modified in the diff. > > **Overview** > Moves MetaMetrics E2E coverage from Mocha/Selenium to Playwright by adding `*.pw.spec.ts` for **App Opened**, **Sentry traces**, **unlock wallet page events**, and updating **Delete MetaMetrics Data** to use `E2E_DRIVER.PLAYWRIGHT`, while removing the old `*.spec.ts` files (including **Sessions**, which is dropped in this PR with no Playwright replacement). > > Fixes flaky or incomplete metrics mocking in Playwright by routing traffic through mockttp via Chromium **`--proxy-server`** and **`--ignore-certificate-errors`** instead of Playwright’s `proxy:` option, so **MV3 service worker** calls (Segment, Sentry, flags) hit the mock server like Selenium. > > Tightens **`setParticipateInMetaMetrics`** unit coverage so **`analyticsId`** stays the same after opt-out **and** opt-back-in, not only after a single opt-out. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 4e6e37f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This pull request updates the version of the `@metamask/bitcoin-wallet-snap` dependency in the `package.json` file to ensure compatibility with the latest features and bug fixes. Dependency update: * Upgraded `@metamask/bitcoin-wallet-snap` from version `^2.0.1` to `^3.0.0` in `package.json` to use the latest major release. ## **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: null ## **Manual testing steps** 1. Interact with the Bitcoin part. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** - [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** > A major-version Snap upgrade can change Bitcoin signing, account, or RPC behavior even without local code edits; manual Bitcoin flows and e2e coverage are the main validation. > > **Overview** > Upgrades the preinstalled **Bitcoin wallet Snap** by bumping `@metamask/bitcoin-wallet-snap` from **^2.0.1** to **^3.0.0** in `package.json`, with matching lockfile resolution to **3.0.0**. > > There are **no extension source changes**—only the bundled Snap version and checksum update. Bitcoin behavior in the wallet now comes from the new major Snap release (features/fixes live in that package). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit a6ea825. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** QA reported the `Best Rate` tag appearing on provider rows whose displayed quote was not the cheapest option ([TRAM-3929](https://consensyssoftware.atlassian.net/browse/TRAM-3929)). Investigation of the reported screenshots showed the backend tags the highest-`amountOut` quote correctly, but the extension derived provider tags from **all** of a provider's quotes while displaying only one (the first non-custom-action quote for the selected payment method). A tag earned by one quote could therefore render next to a different quote's amount. This change derives the tag from the matched (displayed) quote only, matching mobile's `ProviderSelection` behavior, so a tag can never appear next to a different quote's amount. It also vertically centers the tag pill with the provider label: the design-system `Tag` ships with `self-start` in its base classes, which overrode the row's `align-items: center` and pinned the pill slightly high. `RampsProviderListItem` now passes `self-center` (tailwind-merge resolves the conflict in favor of the consumer class). A Storybook story was added for the component (Best Rate / Most Reliable / No Tag / composed rows). Additionally, provider rows now render **all** matching tags instead of only the highest-precedence one (previously-used > most reliable > best rate), in mobile's Quote pill order — a quote that is both most reliable and best rate now shows both pills. ## **Changelog** CHANGELOG entry: Fixed a bug that could show the `Best rate` label on a provider whose displayed quote was not the best rate. ## **Related issues** [TRAM-3929](https://consensyssoftware.atlassian.net/browse/TRAM-3929) ## **Manual testing steps** 1. Run the extension and open the Buy flow. 2. Enter an amount, select a payment method, and open the "Choose provider" modal. 3. Verify the `Best rate` tag appears only on the provider row with the highest crypto amount, and no other row carries the tag. 4. Verify the tag pill is vertically centered with the provider name (not pinned slightly high). 4. When the top provider carries both backend tags (happens when the price leader is also the reliability leader), verify both `Most reliable` and `Best rate` pills render. 5. Verify rows without quotes (listed under "Other options") show no tag. ## **Screenshots/Recordings** ### **After** <img width="1280" height="800" alt="provider-selection-best-rate" src="https://github.com/user-attachments/assets/de68f1b6-464d-4d68-bf38-c6a135c7c77b" /> <img width="1280" height="800" alt="both-tags-modal" src="https://github.com/user-attachments/assets/bd09a4b6-aca2-4756-9256-663c6dc76ab1" /> > [!NOTE] > The first screenshot was taken before the alignment work ## **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. [TRAM-3929]: https://consensyssoftware.atlassian.net/browse/TRAM-3929?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [TRAM-3929]: https://consensyssoftware.atlassian.net/browse/TRAM-3929?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes buy-flow provider labeling logic that influences which provider users perceive as best rate; scoped to ramps UI with tests but affects purchase decision UX. > > **Overview** > Fixes **Best rate** (and related) labels showing on provider rows whose **displayed** quote did not earn that tag. Tag metadata is now taken only from the **matched quote** for the selected payment method (`getProviderTags` + `matchedQuote`), aligned with mobile, instead of scanning all quotes for that provider. > > Provider rows now show **all** applicable pills (previously used, most reliable, best rate) in mobile order, not just the single highest-precedence tag. **`RampsProviderListItem`** accepts a `tags` array, vertically centers tag pills (`self-center`), and lets the provider name truncate beside tags (`min-w-0 flex-1` + name test id). > > Adds Storybook coverage, unit tests for tag derivation and layout, and snapshot updates. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 0400ad4. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…t quote dialog (#45997) <!-- 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 adds an ETH → ETH Robinhood. After quotes load, the test opens `More quotes` dialog, asserts each row’s Total cost checks cheapest-first order, then Back so the selected quote is unchanged. Here's a video of the test execution: https://github.com/user-attachments/assets/62d53a73-b51f-454f-8b11-59d6434b6686 ## **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. Open Swap from the homepage. 2. Set destination network to Robinhood and dest token to ETH. 3. Enter 1 ETH and wait for quotes. 4. Open More quotes and confirm Total cost values and cheapest-first order. 5. Press Back and confirm the original quote is still selected. 6. Submit and confirm activity shows Bridged ETH, Ethereum → Robinhood Chain. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Changes are mostly E2E mocks, page objects, and a test id on bridge quote UI; no bridge transaction or auth logic in production paths. > > **Overview** > Adds **Robinhood chain (4663)** to bridge E2E fixtures—feature flags, token search/popular mocks, privacy allowlist RPC hosts, and a new **ETH→ETH Robinhood** quote stream mock—replacing the prior **Ethereum→Linea** ETH bridge step in the positive-case suite. > > Introduces **`getExpectedQuoteTotalCosts`**, which uses `@metamask/bridge-controller`’s `calcQuoteMetadata` plus shared **`MOCK_SUGGESTED_GAS_FEES`** and spot-price helpers so tests can assert **Select quote** dialog **Total cost** rows (fiat or native fallback) in **cheapest-first** order without hard-coded amounts. The **`bridgeTransaction`** flow and quote page object open **More quotes**, wait for streamed quotes, check each cost, then **Back** without changing the selected quote. > > Adds **`data-testid="bridge-quote-total-cost"`** on the quotes modal Total cost label for stable E2E selectors (snapshot updates only). Network fee checking on the prepare page now waits for a **`$`**-prefixed fee instead of regex-validating arbitrary text. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 56e70ed. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## Version Bump After Release This PR bumps the main branch version from 13.50.0 to 13.51.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.50.0` to `13.51.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.50.0 - Release branch: release/13.50.0 - Platform: extension - Test mode: false --- *This PR was automatically created by the `create-platform-release-pr.sh` script.* Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
## **Description** This is part of #30394 (removing the clipboardWrite permission). The permission was used in a few old Components that are no longer in use. Removed: - AccountDetails + unit tests + storybook + page object + E2E tests - AccountDetailsAuthenticate - AccountDetailsDisplay + unit tests - AccountDetailsKey - AccountDetailsSection - AccountShowPrivateKeyRow + unit tests + storybook - direct dependency on `@lavamoat/lavadome-core` (it's still around as an indirect) - unused strings in `messages.json`, but kept `unexpectedError` in `messageExceptions` - `window.logState()` (it used the clipboard, and no consumer was using it anyway) - changed `docs/state_dump.md` (it referenced `logState()`, which no longer exists, but the previous instructions didn't work anyway) - removed deleted folders from CODEOWNERS - updated `files-to-convert.json` ## **Changelog** CHANGELOG entry: null ## **Related issues** Progresses: #30394 <!--## **Manual testing steps** ## **Screenshots/Recordings** ## **Pre-merge author checklist** ## **Pre-merge reviewer checklist**--> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Removes user-facing export/reveal flows from deleted components; risk is mainly regression if anything still routed to the old modal, plus broad locale and dependency churn in security-sensitive areas. > > **Overview** > Removes **unused legacy account UI** tied to dropping the `clipboardWrite` permission (#30394): the multichain `AccountDetails` modal stack (display, authenticate, key reveal, section), `AccountShowPrivateKeyRow`, related unit/storybook tests, and E2E coverage (`AccountDetailsModal`, account-type-change spec). Multichain account private-key E2E now asserts copy via `PrivateKeyModal`. > > **Cleanup elsewhere:** drops the direct `@lavamoat/lavadome-core` dependency and its type stub; removes `window.logState()` (clipboard-based) while keeping `logStateString`; updates `docs/state_dump.md` to **Settings → Privacy → Download state logs**; prunes obsolete locale keys across locales; adjusts CODEOWNERS, migration dashboard entries, locale verification (`unexpectedError` exception), and jest/console baselines. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit ff9458a. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
release: sync stable to main for version 13.49.0
## **Description** Updated the deprecated modal content component to use the 32px border radius specified by the current design direction. This keeps the modal presentation aligned with the intended visual treatment instead of relying on the previous design-system `LG` radius token. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: N/A ## **Manual testing steps** 1. Build and load the extension. 2. Open a flow that displays a modal dialog. 3. Verify the modal dialog has rounded corners with a 32px radius and that its existing size, padding, and interactions are unchanged. ## **Screenshots/Recordings** Not applicable: this PR updates a small visual token/class value in an existing component. ### **Before** <img width="484" height="522" alt="Screenshot 2026-09-18 at 11 13 38 AM" src="https://github.com/user-attachments/assets/2cc0b6d6-cd64-4f2a-8006-524d0750ddb0" /> ### **After** <img width="452" height="795" alt="Screenshot 2026-09-18 at 11 15 32 AM" src="https://github.com/user-attachments/assets/79d6e529-de1d-4a90-8318-c31b5f6442a9" /> <img width="441" height="297" alt="Screenshot 2026-09-18 at 11 15 36 AM" src="https://github.com/user-attachments/assets/006c44c9-7a06-4edf-9d84-2e9bd66bf2f8" /> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Cosmetic-only change to modal corner radius; no logic, auth, or data handling. > > **Overview** > Updates the legacy **ModalContent** dialog styling so corners match current design (**32px** radius) instead of the old **`BorderRadius.LG`** / **`mm-box--rounded-lg`** treatment. > > In `modal-content.tsx`, the dialog **`Box`** drops the **`borderRadius`** prop and adds the Tailwind class **`rounded-[32px]`** on **`mm-modal-content__dialog`**, so every screen still using this deprecated wrapper picks up the new shape without per-modal edits. Jest snapshots across app, bridge, and confirmation modals were refreshed to reflect the new class list. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 7c97937. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** Upgrades design system packages to align with the [v71.0.0 release](https://github.com/MetaMask/metamask-design-system/releases/tag/v71.0.0). **Packages upgraded:** - `@metamask/design-system-react`: `^0.44.0` → `^0.45.1` **Changes included:** - Updated `AvatarBase` (BadgeNetwork) corner radius to 6px - Updated `ModalContent` corner radius to 32px - Updated `TextField` container border radius from 8px to 12px - Updated snapshots for affected components ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** Feature: Design system upgrade to v71.0.0 Scenario: Core app functionality is unaffected Given I am on the main app screen When I navigate through the primary user flows Then the UI renders correctly with no visual regressions Scenario: Modal and bottom sheet components render correctly Given I interact with BottomSheetDialog and ModalContent components When I view these components in the app Then the corner radii are correctly applied (32px) Scenario: TextField components display correctly Given I interact with TextField components throughout the app When I focus and interact with these fields Then the border radius is correctly applied (12px) ## **Screenshots/Recordings** ### **Before** N/A – dependency-only update ### **After** N/A – dependency-only update <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Dependency-only design-system bump with snapshot updates; visual token changes only, no app logic or security-sensitive paths touched. > > **Overview** > Upgrades **`@metamask/design-system-react`** (`^0.44.0` → `^0.45.1`) and **`@metamask/design-system-shared`** (`^0.38.0` → `^0.39.0`), with matching **`yarn.lock`** updates—no local component code changes. > > Regenerated Jest snapshots reflect upstream styling: modal / bottom-sheet dialogs now use **`rounded-[32px]`** instead of **`rounded-lg`** (e.g. confirm delete network, ramps provider selection), and small network-badge / account-picker icon wrappers switch from **`rounded`** to **`rounded-md`** across bridge and multichain UI tests. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 537b94b. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Token Details used a custom back/options bar plus a separate name row above the price, which did not match the MMDS subpage header pattern (avatar, symbol, badges, and optional contract address in the nav row). This PR replaces that layout with `HeaderSubpage` so identity lives in the header and the chart/price is the first content below it. **What changed:** - Added `AssetPageHeader` using MMDS `HeaderSubpage`: back control, token avatar with network badge, symbol title, security/stock/inactive badges, and a copyable truncated contract address for non-native tokens. - Removed the name row above the balance (`assetDisplayName` / `asset-name` no longer sit above the chart). - Kept the existing `AssetOptions` overflow menu as `endAccessory` (no new header icons). - Switched the overflow trigger to MMDS `ButtonIcon` so it matches the header back button, and dropped the extra right padding that made the more button sit farther from the edge than back. - Updated the token overview E2E back locator to `data-testid="asset-page-back-button"`. ## **Changelog** CHANGELOG entry: Moved token name, avatar, and contract address into the Token Details page header ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/jira/software/c/projects/DSYS/boards/1888?selectedIssue=DSYS-1168 ## **Manual testing steps** 1. Run `yarn start` and load the unpacked extension. 2. Unlock a wallet with Ethereum selected and open Token Details for native ETH (home → asset list → ETH). 3. Confirm the header shows back, ETH avatar with network badge, `ETH` (and verified badge if applicable), and the overflow menu. Confirm there is no name row above the price, and no contract address in the header. 4. Open overflow and confirm View in explorer still works. 5. Open Token Details for an ERC-20 (for example USDC). Confirm the header shows a truncated contract address with copy, and that copy puts the full address on the clipboard. 6. If you have a stock token or inactive asset, confirm those badges still appear next to the symbol in the header. 7. Press back and confirm you return to the previous screen. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <img width="661" height="161" alt="Screenshot 2026-09-17 at 8 13 24 AM" src="https://github.com/user-attachments/assets/5e6bee3b-e046-408f-b340-348011655fc1" /> ### **After** <!-- [screenshots/recordings] --> <img width="658" height="819" alt="Screenshot 2026-09-17 at 9 32 46 AM" src="https://github.com/user-attachments/assets/43a65e70-b5a0-416d-8ec9-425c67d981e9" /> ## **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 layout and design-system component migration on the asset page only; behavior is covered by new unit tests and an updated E2E locator, with no auth or transaction logic changes. > > **Overview** > Token Details now uses a shared **MMDS `HeaderSubpage`** layout instead of a separate back/options row and a name line above the chart. > > A new **`AssetPageHeader`** puts the back control, token avatar with network badge, **symbol** title (with security/stock/inactive badges beside it), and the existing overflow menu in one sticky header. For ERC-20s, a **truncated, copyable contract address** appears under the symbol; native assets omit it. The chart/price is the first content below the header. > > **`AssetOptions`** now uses design-system **`ButtonIcon`** (aligned with the header back control), with layout tweaks so the menu trigger sits flush like the back button. E2E back navigation targets **`data-testid="asset-page-back-button"`**, and unit tests cover the new header behavior. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 5faac8f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Cursor <cursoragent@cursor.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** - Migrate Selenium tests in the Settings area to Playwright. - Implement unsupported PW driver methods, now needed - Add support for artifact download in a test (ie download wallet state) For reviewers: the spec files are exactly the same, just flagging pw tests meaning, the review focus is way smaller than what it initially seems ## **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: https://consensyssoftware.atlassian.net/browse/MMQA-2260 ## **Manual testing steps** 1. yarn 2. yarn start:test 3. On another terminal: yarn test:e2e:playwright:chrome test/e2e/tests/settings/account-token-list.pw.spec.ts ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> https://github.com/user-attachments/assets/b9b52929-cf55-4289-a132-3d0adbe8d00a - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Changes are limited to E2E test infrastructure and spec migration; no production wallet or auth logic is modified. > > **Overview** > Migrates **Settings** end-to-end coverage from Mocha/Selenium (`.spec.ts`) to Playwright (`.pw.spec.ts`), using the same flows and page objects via `withFixtures` with `driverType: E2E_DRIVER.PLAYWRIGHT`. Selenium counterparts for About, account/token balances, backup/export, hide-empty tokens, general settings, search, default address, native-as-main-balance, and localization are removed in favor of the new `.pw.spec.ts` files. > > **PlaywrightDriver** gains behavior needed by these specs: per-page **download** listeners that save exports under `test-artifacts/downloads`, plus implementations for `waitForUrl`, window handle switching/closing, `pasteIntoField`, and `clickElementUsingMouseMove`. **Harness tweaks**: Chrome launches with `--ignore-certificate-errors` so the mock proxy works for MV3 extension service workers; Firefox persistent context sets `acceptDownloads: true`. The backup test stays **Firefox-only** (skipped on `chrome-e2e`), matching the old Selenium Chrome skip. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit de9690e. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…46095) ## **Description** Chainlist.org proposes RouteMesh RPC URLs such as `https://lb.routeme.sh/rpc/evm/30` when adding networks (for example Rootstock Mainnet). Two separate validation problems made that flow report misleading errors. **1. False "unknown provider" warning.** RouteMesh hosts are not in the chainid.network safe-chain list, so the add-network confirmation showed an "unknown provider" warning on the RPC row. This change treats the exact HTTPS RouteMesh path `/rpc/evm/<decimalChainId>` as a known provider only when the embedded chain ID matches the requested EIP-3085 chain ID. Wrong-chain paths and spoofed hostnames still warn. **2. Misleading "Is your RPC URL correct?" error.** Once RouteMesh's keyless public tier is exhausted, it answers `eth_chainId` with HTTP 429 and JSON-RPC error code `-32029` ("public rate limit exceeded — sign up for free at https://routeme.sh to continue"). `jsonRpcRequest` collapsed that into a generic failure, so the add-network flows told users "Could not fetch chain ID. Is your RPC URL correct?" even though the URL was correct — and the provider's own explanation was thrown away. `jsonRpcRequest` now throws a `JsonRpcRequestError` carrying the JSON-RPC error code and HTTP status, and `isRpcRateLimitError` lets callers tell throttling apart from an unreachable or incorrect endpoint. The add-RPC-URL form, networks form, and add-chain confirmation alerts surface a rate-limit message instead. Submission is still blocked, since a throttled endpoint would produce a broken network. Note that this does not make a rate-limited endpoint usable. The RouteMesh public tier failing is an upstream issue with what chainlist.org advertises; this change makes MetaMask report the cause accurately instead of blaming the user's URL. ## **Changelog** CHANGELOG entry: Fixed misleading errors when adding a custom network whose RPC provider is rate limiting requests or uses RouteMesh (`lb.routeme.sh`). ## **Related issues** Fixes: WPN-1930 Related: #45797 ## **Manual testing steps** False "unknown provider" warning: 1. Run the extension and open a dapp at https://chainlist.org. 2. Add Rootstock Mainnet (chain ID 30) via Connect Wallet so MetaMask shows the add-network confirmation. 3. Confirm the RPC field shows `lb.routeme.sh/rpc/evm/30`. 4. Click the RPC warning/info control. 5. Verify the "submitted RPC URL value does not match a known provider for this chain ID" alert is **not** shown for this URL. 6. Confirm that adding a network with a different host, or a RouteMesh path for a different chain ID, still shows the unknown-provider warning. Rate-limit reporting: 7. Go to Settings > Networks > Add a network > Add RPC URL and enter `https://lb.routeme.sh/rpc/evm/30`. 8. Verify the error reads "This RPC provider is limiting requests. Try again later or use a different RPC URL." rather than "Could not fetch chain ID. Is your RPC URL correct?". 9. Verify the Add URL button stays disabled. 10. Replace the URL with a working endpoint such as `https://public-node.rsk.co` and verify no error appears and the button becomes enabled. 11. Enter an unreachable URL such as `https://not-an-rpc.example.com` and verify the original "Could not fetch chain ID. Is your RPC URL correct?" error still appears. <!-- ## **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. --> Made with [Cursor](https://cursor.com) --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
…46418) <!-- 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 stabilizes the Shield crypto annual-plan E2E after picking a payment token. **Root cause:** - The test opens the Shield plan page from the entry modal and chooses the annual plan. - It then clicks Pay with crypto to pick USDC. - The fixture seeds both USDC and USDT, so Pay with crypto opens a nested asset picker and does not close the Change payment method modal. - After clicking USDC, the helper returns right away. - The test then clicks Continue. - Continue is in the DOM, but the Change payment method overlay still covers it, so the click cannot reach the button. **Solution:** - Wait for the nested asset picker (`asset-picker-modal`) after clicking Pay with crypto, so the token list is on screen before picking USDC. - After picking USDC, wait until the Change payment method modal (`shield-payment-modal`) is gone, using the plan page as a guard, so Continue is uncovered before the one Continue click. Slack: https://consensys.slack.com/archives/CTQAGKY5V/p1789633666997879?thread_ts=1789633473.891219&cid=CTQAGKY5V ## **Changelog** CHANGELOG entry: null <!-- ## **Related issues** Fixes: --> ## **Manual testing steps** 1. Start a test build with `yarn start:test`. 2. Run: ```bash SELENIUM_BROWSER=chrome yarn test:e2e:single test/e2e/tests/shield/shield-plan-subscription.spec.ts --debug --leave-running ``` 3. Confirm the case `should get started on entry modal - annual plan` picks USDC, waits for the Change payment method modal to close, then clicks Continue successfully. ## **Screenshots/Recordings** ### **Before** CI screenshot at failure: Change payment method overlay still open (Pay with USDC selected, Pay with card unselected). Continue is behind `mm-modal-content`. The test timed out on `clickContinueButton`. <img width="780" height="493" alt="image" src="https://github.com/user-attachments/assets/91e40062-eff2-40e3-860c-f8e88632404a" /> ### **After** No product UI change. After picking USDC, the helper waits until the payment modal is gone, then Continue is clicked once. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > E2E page-object timing only; no production UI or application logic changes. > > **Overview** > Fixes flaky Shield annual-plan E2E where **Continue** was clicked while the **Change payment method** overlay still blocked it after choosing USDC. > > `selectCryptoPaymentToken` now **waits for the nested asset picker** (`asset-picker-modal`) before selecting the token, then **waits until `shield-payment-modal` is gone** (scoped with the plan page guard) so the helper only returns once **Continue** is clickable. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 57e5204. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Cursor <cursoragent@cursor.com>
<!-- Please submit this PR as a draft initially. Do not mark this as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Stabilizes the Trezor hardware-wallet E2E that opens Connect hardware from the account list. **Root cause:** - The test logs in, opens the account menu, and lands on the Accounts screen. - It waits until the footer no longer says Syncing, then clicks Add wallet and looks for Hardware wallet. - Add wallet can look ready while the list is still updating balances and other accounts. - The click is recorded as success, but the wallet never leaves Accounts. - The next wait for the Hardware wallet option times out on the Accounts screen. **Solution:** - Wait until Add wallet is enabled and not showing Syncing, and stays that way for 2 seconds, so the click happens after the footer stops flickering. - Click Add wallet once after that wait. Hardware wallet, import, and watch-account flows use the same helper so they do not hit the same race. - Account list load uses that same wait instead of a short "Syncing is gone" check, so the page is not marked loaded while the footer is still changing. **Slack:** https://consensys.slack.com/archives/CTQAGKY5V/p1789723483575219?thread_ts=1789719783.184109&cid=CTQAGKY5V ## **Changelog** CHANGELOG entry: null <!-- ## **Related issues** Fixes: --> ## **Manual testing steps** 1. Start a test build with `yarn start:test` if one is not already running. 2. Run `SELENIUM_BROWSER=chrome yarn test:e2e:single test/e2e/tests/hardware-wallets/trezor/trezor-account.spec.ts`. 3. Confirm the test opens Accounts, reaches the hardware wallet picker, and unlocks the first Trezor account. ## **Screenshots/Recordings** <img width="1366" height="682" alt="image" src="https://github.com/user-attachments/assets/8a925f13-7aa8-45d7-a21e-527216284beb" /> ### **Before** CI screenshot at failure: still on Accounts. Account 1 and Add wallet are visible. The Hardware wallet option is missing because Add wallet never opened the choose-wallet-type page. ### **After** No product UI change. After Accounts loads, the helper waits until Add wallet stays enabled, then clicks it once and the Hardware wallet option is on screen. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Test-only page object changes; no production UI or wallet logic. > > **Overview** > Fixes flaky Trezor (and related) E2E flows where **Add wallet** was clicked while the account list footer was still syncing or flickering, so navigation to choose-wallet-type never happened. > > The account list page object now **waits until Add wallet is enabled, not showing Syncing, and stays that way for 2s** (`waitForAddWalletButtonStablyReady`), then clicks via a shared **`clickAddWalletButton`** helper. Hardware wallet, import, watch-account, and other flows that opened Add wallet directly now use that helper. > > **`waitUntilSyncingIsCompleted`** (used when marking the list loaded and before add-account) delegates to the same stable-ready wait, bumps the default timeout from 10s to 15s, and drops the old “Syncing gone + assert Add wallet visible” sequence. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 801b971. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Cursor <cursoragent@cursor.com>
…tils to TypeScript (#46430) <!-- 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** Migrate three `shared/lib` modules and their colocated tests from JavaScript to TypeScript. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: MetaMask/MetaMask-planning#7405 ## **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 provider injection gating and swaps quote/tx construction paths; most changes are typing, but guarded address-book updates and query-string construction could subtly change runtime behavior. > > **Overview** > Migrates **`provider-injection`**, **`swaps-utils`**, and **`updateTxData`** (plus colocated tests) from JavaScript to TypeScript and drops them from the TS migration dashboard list. > > **Provider injection** gains explicit typings and builds the eligibility URL from `window.location.href` instead of passing `window.location` directly. > > **`swaps-utils`** is reimplemented as **`swaps-utils.ts`** with typed API/quote validators and request shapes; trade fetching now builds query strings via `URLSearchParams` with stringified values (including `enableDirectWrapping`). Tests drop unused `fetchTradesInfo` arguments that no longer exist on the typed input. > > **`updateTxData`** exports **`UpdateTxDataMeta`** / **`UpdateTxDataParams`** tied to `TransactionMeta`, and only calls **`addToAddressBookIfNew`** when the callback and `toAddress` / `toAccounts` are all present. > > **`swaps.util.ts`** validator helpers are aligned with the shared module’s optional `(value: unknown)` validators. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit f7d2879. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…es typed address without 0x prefix and sends TST` (#46499) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** The spec is flaky as after confirming the transaction, we try to click on the Confirmed tx to see the details, but sometimes the tx toast notifications appears, intercepting the click <img width="1033" height="302" alt="image" src="https://github.com/user-attachments/assets/0c205b64-19ae-4d01-b7e9-7e4e14711147" /> Now we clickElementSafe, so if the toast is there, we close it ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: ## **Manual testing steps** 1. Check ci ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <img width="780" height="493" alt="image" src="https://github.com/user-attachments/assets/6245aeca-9857-4062-afd2-0d824f215adb" /> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Test-only change with no production code impact. > > **Overview** > Fixes flakiness in the **ERC20 “normalizes typed address without 0x prefix and sends TST”** send E2E by dismissing the post-confirmation transaction toast before opening the confirmed activity entry. > > After the tx is confirmed and the activity list is shown, the test now uses **`TxToastNotification.closeToastNotification()`** so the overlay does not block or race with **`clickConfirmedTransaction()`** when verifying the normalized address in the activity log. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 523c4ad. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** Added Sentry performance traces for the unified Swaps/Bridge experience so the extension reports the same key dashboard signals as Mobile. The traces cover bridge view loading, quote fetching, quote stream completion, balances, token selection, and relevant entry-point/request metadata. The implementation also carries the view trace across bridge navigation and avoids treating React StrictMode's development-only effect probe as a cancelled page visit. ## **Changelog** CHANGELOG entry: null ## **Related issues** SWAPS-5033: https://consensyssoftware.atlassian.net/browse/SWAPS-5033 ## **Manual testing steps** 1. Run the extension with `yarn webpack --watch` and load the unpacked build in Chrome. 2. Open the unified Swaps/Bridge page from the extension homepage and from a token detail page; also open it through a bridge deep link when available. 3. Complete a normal quote request, refresh quotes, and exercise an unsuccessful/no-quote request. 4. In the extension service-worker console, verify the relevant trace lifecycle logs, then confirm the corresponding traces and result attributes appear in the MetaMask Sentry dashboard. <!-- ## **Screenshots/Recordings** Not applicable: this change adds telemetry and does not change the rendered UI. --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md) 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] > **Low Risk** > Telemetry-only changes with no user-facing swap logic; minor risk of misleading metrics if lifecycle edge cases (navigation, debounce, StrictMode) are wrong. > > **Overview** > Adds **Sentry performance tracing** for the unified Swaps/Bridge UI so extension dashboards can align with Mobile: view load, quote fetch, balances, and token API latency. > > **Page load (`Swap View Loaded`)** now starts on entry (navigation hook or deep link), carries a trace id through router state, and ends when tokens, source balance, and (if prefilled) the quote surface are ready—or is marked **cancelled** on real unmount (StrictMode-safe). > > **Quote fetch** moves to a shared `swapQuoteFetchTrace` helper: debounced starts cancel superseded requests; completion uses **success**, **no_quotes** (with stream reason), **error**, or **cancelled**, and ignores stale quotes when the asset pair changed. > > Other **cache-miss** fetches emit **`bridge.data_fetch`** traces for popular tokens and token search; source balance reads use explicit start/end with **success/error**. **`Swap Quotes Fetched`** tags the legacy background quote thunk with the same operation. > > New **`docs/swaps/swaps-sentry-reference.md`** documents trace names, ops, panel titles, and example Sentry filters. Tests and navigation expectations were updated for trace ids and entry-point metadata. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 5516a52. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…46338) ## **Description** Hardware wallet accounts cannot sign the batch that executes a Money Account deposit or withdrawal, but the extension still offered them in two places: 1. **The account picker.** The "From" row on the Money Account confirmation listed every EVM account, filtered only by `isEvmAccountType`. A user could select a Ledger and only then hit a blocking alert — a dead end, since the account was offered and then rejected. 2. **The entry point.** `useMoneyAccountDeposit` / `useMoneyAccountWithdrawal` seeded `txParams.from` from the globally selected account, checking only that it was EVM. A user on a hardware wallet who tapped "Add funds" landed on the confirmation already blocked, having never made a choice. This PR closes both paths: - Hardware accounts are **hidden from the account picker** for flows that forbid them (Money Account deposit/withdraw, Perps, Predict). - The funding/recipient account is resolved by a new `selectMoneyFundingAccount`, which prefers the globally selected account and **falls back to the user's first eligible EVM account** when it is ineligible. Initiation now fails only when the user has no eligible account at all. The blocked transaction-type lists moved from a private list inside the alert hook into `constants/pay.ts`, behind a shared `useIsPayHardwareBlocked` hook. The picker and the alert now read the same logic, so the list a user can choose from and the alert that blocks them cannot drift apart. **Notes for reviewers:** - `usePayHardwareAccountAlert` is intentionally **kept**, not deleted as redundant. It still guards addresses the picker never vetted — deep links and any other entry point that sets `txParams.from` directly. It is now documented as a backstop. - The fallback reads `internalAccounts.accounts`, which `AccountsController` rebuilds in keyring order, so "first" matches what the rest of the UI treats as first. It deliberately avoids the balance-joined ordered-accounts selector, which would pull keyring and balance state into entry points that only need an address. - The Money Account itself can never be selected as its own funding source: `AccountsController` excludes the Money keyring from `internalAccounts` entirely (it is owned by `MoneyAccountController`). - The fallback is **silent** — the user is not told their funding account was substituted. The From row does display it and it remains editable. Happy to add an explicit toast/inline note if product prefers. ## **Changelog** CHANGELOG entry: Fixed an issue where a hardware wallet account could be selected for a Money Account deposit or withdrawal, which is not supported ## **Related issues** Fixes: [CONF-1980](https://consensyssoftware.atlassian.net/browse/CONF-1980) ## **Manual testing steps** Requires a wallet with at least one hardware wallet account (Ledger/Trezor) and at least one non-hardware EVM account, with the Money Account feature enabled. **Account picker no longer lists hardware accounts** 1. Select any non-hardware account. 2. Go to the Money home page and tap **Add** to start a deposit. 3. On the amount screen, tap the **From** account pill to open the account picker. 4. Verify no hardware wallet accounts are listed. 5. Verify a wallet whose accounts are *all* hardware does not appear as an empty section header. 6. Verify non-hardware accounts (HD and imported) are still listed and selectable. 7. Repeat steps 2–6 for **Send → Withdraw** to confirm the withdraw flow behaves the same. **Hardware account is not used to create the transaction** 8. Switch the globally selected account to a **hardware wallet** account. 9. From the Money home page, tap **Add**. 10. Verify the confirmation opens normally with **no blocking "Wallet not supported" alert**. 11. Verify the **From** row shows a non-hardware account (the first eligible one), not the selected hardware account. 12. Repeat steps 9–11 for the withdraw flow, confirming the destination account is the non-hardware account. **Unrelated flows are unchanged** 13. With a hardware account selected, start a regular send or a contract interaction. 14. Verify the account picker still lists hardware accounts and the flow is unaffected. <!-- ## **Screenshots/Recordings** ### **Before** ### **After** --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. [CONF-1980]: https://consensyssoftware.atlassian.net/browse/CONF-1980?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes which account funds or receives Money flows and silently substitutes when hardware is selected; mistakes could send funds from/to the wrong address, though behavior is covered by new selector and hook tests. > > **Overview** > Hardware wallets cannot sign Money Account deposit/withdraw batches, but the extension still let users pick them or land on a blocked confirmation when a Ledger/Trezor was globally selected. > > **Entry points** now resolve funding/recipient via **`selectMoneyFundingAccount`**: use the selected account when it is an eligible non-hardware EVM account, otherwise **fall back to the first eligible EVM account** in wallet order. Deposit and withdraw hooks only fail when no eligible account exists. > > **Confirmations** hide hardware accounts in the **From/To account picker** for Pay flows that forbid them (Money deposit/withdraw, Perps, Predict, and flag-gated mUSD conversion). `getEvmAccountsGroupedByWallet` and `AccountSelectModal` gain an **`excludeHardwareAccounts`** option; `FromAccountRow` drives it from a new shared **`useIsPayHardwareBlocked`** hook. Blocked transaction-type lists live in **`constants/pay.ts`** so the picker and **`usePayHardwareAccountAlert`** (kept as a backstop for deep links and pre-seeded `txParams.from`) stay aligned. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit f63a791. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
… info (#46507) ## **Description** Small polish to the ramps provider selection screen: - The provider selection modal heading now reads "Choose providers" (was "Choose provider") to match the plural list it introduces. - The "Most reliable" provider tag now renders with `Info` severity (blue) instead of `Neutral` (gray); "Best rate" remains `Success` (green). - Synced the `rampsChooseProvider` string in `en_GB` with `en`. ## **Changelog** CHANGELOG entry: Updated the buy flow's provider selection screen to read "Choose providers" and to show the "Most reliable" tag in blue. ## **Related issues** <!-- No Jira ticket id is derivable from the branch name (`jira-check`). --> Fixes: [TRAM-3967](https://consensyssoftware.atlassian.net/browse/TRAM-3967?atlOrigin=eyJpIjoiZDViZjBiNGM0NDVjNGY0MWJhNzNiMjU4NDk3NzZiNmQiLCJwIjoiaiJ9) ## **Manual testing steps** 1. Build the extension and load it in Chrome. 2. Onboard a wallet (import or create). 3. From the wallet home, open the buy flow and select ETH on Ethereum. 4. On the build-quote screen, click "change providers". 5. Verify the modal heading reads "Choose providers". 6. Verify the "Most reliable" tag pill renders blue and the "Best rate" tag renders green. ## **Screenshots/Recordings** ### **After** <img width="1280" height="800" alt="03-choose-providers-modal-1789980333869" src="https://github.com/user-attachments/assets/2586100d-1679-4aab-bb04-bee952ce9e8e" /> ## **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 followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Code Review Guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've confirmed code meets the repo's coding standards. - [ ] I've tested the changes per the manual testing steps. [TRAM-3967]: https://consensyssoftware.atlassian.net/browse/TRAM-3967?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Copy, styling, and tag severity only in the ramps buy provider-selection UI; no auth, payments, or backend logic changes. > > **Overview** > Polishes the ramps **provider selection** modal copy and tag styling. > > The modal title string `rampsChooseProvider` is updated to **"Choose providers"** in `en` and `en_GB`, and the dialog gets an explicit **`rounded-[32px]`** class on modal content (snapshots reflect the heading and class reorder). > > **Most reliable** provider pills now use **`TagSeverity.Info`** (blue) instead of **Neutral**, aligning with **Previously used**; **Best rate** stays **Success** (green). Tests, stories, and snapshots are updated for the new copy and severities. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 3d7cc48. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** Several Core Extension UX actions still override the shared pill-shaped button default with rounded-square corners. This removes those overrides from multichain import/network actions and toast actions, and updates critical-error recovery buttons to use pill-shaped corners. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** 1. Open the affected import, network, toast, and critical-error surfaces. 2. Verify their text/action buttons have pill-shaped corners in their normal state. 3. Verify disabled, hover, pressed, and loading states retain their existing visual behavior. ## **Screenshots/Recordings** Before/after Storybook screenshots will be added as inline PR comments where stories are available; temporary sandbox stories will cover other components. ### **Before** ### **After** ## **Pre-merge author checklist** - [ ] I've followed MetaMask Contributor Docs and Extension Coding Standards. - [ ] I've completed the PR template to the best of my ability. - [ ] I’ve included tests if applicable. - [ ] I’ve documented code using JSDoc if applicable. - [ ] I’ve applied the right labels. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR. - [ ] I confirm that this PR includes the necessary testing evidence. Made with [Cursor](https://cursor.com) --------- Co-authored-by: Cursor <cursoragent@cursor.com>
…46508) <!-- CURSOR_AGENT_PR_BODY_BEGIN --> ## **Description** When viewing a native asset on a different network than the currently selected one (e.g., viewing ETH on Mainnet while connected to a custom network), clicking "View on explorer" was incorrectly opening the custom network's block explorer instead of Etherscan. The root cause was that `getRpcPrefsForCurrentProvider` returned the `rpcPrefs` for the **currently selected network**, not the network of the asset being viewed. When the user had a custom network selected, its `blockExplorerUrl` was passed to `getAccountLink`, overriding the correct explorer for the asset's chain. This fix looks up the network configuration for the asset's specific `chainId` using `selectNetworkConfigurationByChainId` and extracts the `blockExplorerUrl` from that configuration instead of using the current provider's rpcPrefs. ## **Changelog** CHANGELOG entry: Fixed a bug where clicking "View on explorer" for a token would open the wrong network's block explorer ## **Related issues** Fixes: #46372 ## **Manual testing steps** 1. Add any new custom network to MetaMask (with a custom block explorer URL) 2. Switch to or remain on Ethereum Mainnet 3. Navigate to the ETH native asset page 4. Click the 3-dot menu → "View on explorer" 5. Verify that Etherscan opens (not the custom network's explorer) 6. Switch to the custom network and view its native asset 7. Click the 3-dot menu → "View on explorer" 8. Verify that the custom network's explorer opens correctly <!-- ## **Screenshots/Recordings** ### **Before** ### **After** --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-a6cf49a0-230c-4eba-8c6f-bffa5cbcdeef?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a href="https://cursor.com/background-agent?bcId=bc-a6cf49a0-230c-4eba-8c6f-bffa5cbcdeef&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> </div> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Amélie <ameliejyc@users.noreply.github.com>
## **Description** Split from #45897. Moves ref writes out of render and fixes `react-hooks/exhaustive-deps` in multichain, compliance, and misc pages for MetaMask-planning#6402. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: MetaMask/MetaMask-planning#6402 ## **Manual testing steps** <!-- ## **Screenshots/Recordings** ### **Before** ### **After** --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. <!-- ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Refactors compliance gating, seed reveal, and mUSD tracing lifecycle with hook-timing changes; intent is parity but these paths are security- or metrics-sensitive. > > **Overview** > Clears a batch of **`react-hooks/refs`** (and related) suppressions by stopping ref writes and ad-hoc render updates across multichain menus, compliance, subscriptions, and several settings/confirm flows. > > **Popover/menu anchoring** now uses callback refs plus state (`referenceElement` / `anchorElement`) so `Menu`/`Popover` get a DOM node after commit—touched in account menus, permission/connected-account options, dropdown editor, and network menu stories. **`useComplianceGate`** moves `currentAddressKeyRef` and `checkComplianceRef` updates into **`useLayoutEffect`** instead of during render. > > **Other behavior-preserving refactors:** confirm **expandable row** height via measured state; **`useNetworkManager`** reads URL `view` in `handleClose` deps instead of a ref; **`useMusdConversionConfirmTrace`** tracks active traces with state (plus a test when `transactionId` clears after confirm); **`reveal-seed`** and **QR sync scan** replace render-time ref/state hacks with explicit state/effects; **`useSubscriptionError`** syncs the error ref in layout effect. **`eslint-suppressions.json`** drops the fixed file entries, and **multichain account menu** tests **`waitFor`** the menu button after the ref callback change. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 3d130f4. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** The wallet creation success page settings action still applies a rounded-square radius. This removes the explicit radius so the action inherits the shared pill-shaped button style. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** 1. Complete wallet creation and open the creation-successful page. 2. Verify the Manage default settings action has pill-shaped corners. 3. Verify the settings icon, label alignment, navigation, and responsive width remain unchanged. ## **Screenshots/Recordings** Before/after Storybook screenshots will be added as inline PR comments. ### **Before** ### **After** ## **Pre-merge author checklist** - [ ] I've followed MetaMask Contributor Docs and Extension Coding Standards. - [ ] I've completed the PR template to the best of my ability. - [ ] I’ve included tests if applicable. - [ ] I’ve documented code using JSDoc if applicable. - [ ] I’ve applied the right labels. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR. - [ ] I confirm that this PR includes the necessary testing evidence. Made with [Cursor](https://cursor.com) Co-authored-by: Cursor <cursoragent@cursor.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Thinner alternative to #46510 for MUSD-1412. Duplicate deposit toasts happen because Pay source legs fire `transactionStatusUpdated` before Redux has the parent's `requiredTransactionIds`. The generic listener then shows "Transaction submitted" next to the Money deposit toast. This keeps `useTransactionEventToasts` generic. The only change there is one extra skip: `isKnownMoneyBatchChild(id)` The money toast listener fills a small UI registry from messenger payloads (`requiredTransactionIds`), so the generic listener can exclude those children without waiting on Redux and without deferring unrelated toasts. No pending/confirm/fail branching, no `store.subscribe`, no timeout in the generic listener. ## **Changelog** CHANGELOG entry: Fixed duplicate notifications shown during Money Account deposits ## **Related issues** Fixes: [MUSD-1412](https://consensyssoftware.atlassian.net/browse/MUSD-1412) [MUSD-1413](https://consensyssoftware.atlassian.net/browse/MUSD-1413) ## **Manual testing steps** 1. Open Money Account and start a deposit. 2. Pay with ETH on Arbitrum (the known-repro route). 3. Confirm the deposit. Verify only the Money deposit/convert toast appears — not a second "Transaction submitted" toast. 4. Confirm a normal send still shows "Transaction submitted" immediately. ## **Screenshots/Recordings** ### **Before** <img width="752" height="370" alt="Screenshot 2026-09-18 at 16 29 40" src="https://github.com/user-attachments/assets/1462fa3d-cff4-48c2-8d68-9f4f885aa0e1" /> ### **After** <img width="791" height="662" alt="Screenshot 2026-09-21 at 13 35 57" src="https://github.com/user-attachments/assets/ea527680-9430-4d8b-944a-2dc62a301381" /> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. [MUSD-1412]: https://consensyssoftware.atlassian.net/browse/MUSD-1412?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > UI-only toast filtering with a small module-scoped registry; behavior is covered by new unit tests and does not touch auth, signing, or transaction submission. > > **Overview** > Fixes duplicate deposit notifications by tracking Money batch **child transaction IDs** from messenger payloads before Redux catches up. > > Adds an in-memory **`money-batch-registry`** that records each Money deposit batch’s `requiredTransactionIds`. The Money account toast listener **registers** the batch on pending lifecycle events and **clears** it on confirm or failure (including when no success toast is shown). > > The generic transaction toast hook now **bails out early** when `isKnownMoneyBatchChild(id)` is true, so Pay/funding legs (e.g. relay deposits) no longer trigger a second “Transaction submitted” toast alongside the Money deposit toast. Unrelated relay deposits and normal sends are unchanged. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit b39d4d0. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: ffmcgee <51971598+ffmcgee725@users.noreply.github.com>
## **Description** The money account balance Add action still applies a rounded-square radius despite using the shared button component. This removes the explicit radius so the action inherits the pill-shaped button default. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** 1. Open the money account balance surface with the Add action visible. 2. Verify the Add action has pill-shaped corners. 3. Verify loading, disabled, and balance-state transitions remain unchanged. ## **Screenshots/Recordings** Before/after Storybook screenshots will be added as inline PR comments where a story is available; a temporary sandbox story will cover this component if needed. ### **Before** ### **After** <img width="400" alt="After" src="https://raw.githubusercontent.com/MetaMask/metamask-extension/screenshots/visual-regression-extension/pr-46475/after/earn-money-account-balance.png" /> ## **Pre-merge author checklist** - [x] I've followed MetaMask Contributor Docs and Extension Coding Standards. - [x] I've completed the PR template to the best of my ability. - [x] I’ve included tests if applicable. - [x] I’ve documented code using JSDoc if applicable. - [x] I’ve applied the right labels. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR. - [ ] I confirm that this PR includes the necessary testing evidence. Made with [Cursor](https://cursor.com) Co-authored-by: Cursor <cursoragent@cursor.com>
674c2d0 to
53752b4
Compare
Builds ready [53752b4] [reused from 674c2d0]
⚡ Performance Benchmarks (Total: 🟢 7 pass · 🟡 4 warn · 🔴 2 fail)
Bundle Size Diffs [🚨 Warning! Bundle size has increased!]
Cherry-picks (10 commits)
Changelog (127 commits since v13.50.0)
AI Test Plan
Cherry-Pick Scenarios (4)High Risk Scenarios (1)1. State Migrations - Crash resilienceRisk Level: HIGH Why This Matters: Cherry-pick 46683 fixes a migration crash; regressions here can brick wallets or corrupt data on upgrade. Test Steps:
Medium Risk Scenarios (3)1. Transaction Confirmations - Money account perps pay feature gatingRisk Level: MEDIUM Why This Matters: Cherry-pick 46709 gates a high-variance confirmation path; incorrect gating can expose unfinished UX or break confirmations. Test Steps:
2. Analytics - Money account events parityRisk Level: MEDIUM Why This Matters: Cherry-pick 46752 ensures parity with mobile tracking; event schema mistakes can harm analytics quality or cause runtime errors. Test Steps:
3. Token Management - Stellar asset details via CAIP19 routeRisk Level: MEDIUM Why This Matters: Cherry-pick 46764 prioritizes route-derived CAIP19 IDs; incorrect precedence can show the wrong asset or crash the asset details page. Test Steps:
Release Scenarios (7)High Risk Scenarios (5)1. State Migrations (upgrade robustness)Risk Level: HIGH Why This Matters: Multiple migration files were modified and a new migration (228) was added; migration regressions can corrupt user data or block startup. Test Steps:
2. Onboarding - Passkey PRF Migration (successful path)Risk Level: HIGH Why This Matters: A new, user-facing migration flow was introduced; failures can block onboarding or leave keys/accounts unusable. Test Steps:
3. Onboarding - Passkey PRF Migration (cancel, retry, and gating)Risk Level: HIGH Why This Matters: Edge cases (deferrals, rejections, ineligible users) must be resilient to avoid onboarding loops or broken states. Test Steps:
4. Token/NFT Management - Asset lists across networksRisk Level: HIGH Why This Matters: Core asset selector logic changed; incorrect selectors/migrations can hide, duplicate, or misattribute assets across networks. Test Steps:
5. Session/Pending Approvals - App state (lock/unlock and resume)Risk Level: HIGH Why This Matters: App-state-controller changes can break how pending approvals survive lock/unlock and UI lifecycle transitions. Test Steps:
Medium Risk Scenarios (2)1. Alerts & Notifications - Multiple alert modal and connection indicatorsRisk Level: MEDIUM Why This Matters: The unconnected-account alert component was removed and alert modal logic was changed; misbehavior can mislead users or block actions. Test Steps:
2. Analytics/MetaMetrics - Consent gating and event integrityRisk Level: MEDIUM Why This Matters: Analytics controller and platform adapter changes risk over-collection, under-collection, or runtime errors that could impact core flows. Test Steps:
Teams Sign-off StatusSigned off: None yet Awaiting sign-off (7): Generated by AI Test Plan Analyzer (gpt-5) at 2026-10-01T02:16:18.543Z AI generated test plan (JSON): test-plan-13.51.0.json |
|
@metamaskbot update-attributions |
|
Attributions updated |
Builds ready [be02bc1]
⚡ Performance Benchmarks (Total: 🟢 8 pass · 🟡 3 warn · 🔴 2 fail)
Bundle Size Diffs [🚨 Warning! Bundle size has increased!]
Cherry-picks (11 commits)
Changelog (128 commits since v13.50.0)
AI Test Plan
Cherry-Pick Scenarios (5)High Risk Scenarios (2)1. Migration Stability (crash on upgrade)Risk Level: HIGH Why This Matters: Cherry-pick 46683 fixes a migration crash that could block users on upgrade; verifying recovery and data integrity is critical. Test Steps:
2. Confirmations: Money Account Perps Pay feature flag gatingRisk Level: HIGH Why This Matters: Cherry-pick 46709 gates a transaction-type UI by feature flag. Incorrect gating can expose unfinished flows or block valid transactions. Test Steps:
Medium Risk Scenarios (3)1. Stellar Asset Details: CAIP-19 route-derived ID priorityRisk Level: MEDIUM Why This Matters: Cherry-pick 46764 prioritizes route-derived CAIP-19 IDs. Without this, users could see the wrong Stellar asset details. Test Steps:
2. Privacy Messaging: Basic Functionality copy and settingsRisk Level: MEDIUM Why This Matters: Cherry-pick 46640 fixes Basic Functionality privacy messaging; incorrect copy or rendering can mislead users about data collection. Test Steps:
3. Analytics parity for Money Account eventsRisk Level: MEDIUM Why This Matters: Cherry-pick 46752 ensures parity with mobile for Money Account analytics. Misfired or missing events break cross-platform analytics consistency. Test Steps:
Release Scenarios (9)High Risk Scenarios (5)1. State Migrations (upgrade from prior versions)Risk Level: HIGH Why This Matters: Many migration files changed and a new migration 228 was added. Any migration fault can brick wallets on upgrade or silently drop assets/connections. Test Steps:
2. Onboarding - Passkey PRF Migration (success path)Risk Level: HIGH Why This Matters: New passkey PRF migration page/hook was added. Any break can block unlock, strand users on a modal, or degrade passkey login. Test Steps:
3. Alert System Regression (removed Unconnected Account Alert + multiple-alert-modal updates)Risk Level: HIGH Why This Matters: The unconnected account alert UI was removed and multiple-alert-modal changed. This can cause missing prompts, stuck modals, or mis-queued critical requests. Test Steps:
4. Assets: Token/NFT discovery and selectors (cross-network)Risk Level: HIGH Why This Matters: Selectors for assets were heavily updated. Any mistake can misreport balances, hide tokens/NFTs, or double-count across networks. Test Steps:
5. Analytics & Privacy Controls (controllers and platform adapter)Risk Level: HIGH Why This Matters: Analytics controller and adapter changed. Incorrect gating could leak data when opted out or drop critical events when opted in. Test Steps:
Medium Risk Scenarios (4)1. Passkey PRF Migration (skip/defer and re-prompt behavior)Risk Level: MEDIUM Why This Matters: Defer flows can loop or suppress future prompts. Users must never be blocked from core actions or lose the ability to migrate later. Test Steps:
2. Transaction Confirmation Flow (general regression, EIP-1559 UI)Risk Level: MEDIUM Why This Matters: Broad UI changes raise the risk of confirmation regressions that can mislead users about fees or hinder signing. Test Steps:
3. Asset List Filter: Home network vs All networksRisk Level: MEDIUM Why This Matters: Filter logic impacts asset visibility and totals. A broken filter can confuse users about balances and holdings. Test Steps:
4. Connected Sites and Permissions after migrationRisk Level: MEDIUM Why This Matters: Migrations and alert changes can inadvertently drop or corrupt site permissions, breaking dapp connectivity. Test Steps:
Teams Sign-off StatusSigned off: None yet Awaiting sign-off (9): Generated by AI Test Plan Analyzer (gpt-5) at 2026-10-01T02:52:21.573Z AI generated test plan (JSON): test-plan-13.51.0.json |
|
@SocketSecurity ignore npm/@metamask/client-mcp-core@0.10.0 |
There was a problem hiding this comment.
Modern Web Guidance review
Reviewed UI changes in this release against modern-web-guidance (accessibility + interest-triggered tooltips). Actionable findings are inline on the ramps payment-method quote tooltip work.
Summary
- Nested interactive controls on payment-method rows (selectable row + warning tooltip trigger).
- Missing accessible name on the icon-only warning trigger.
- Native
popover="hint"positioning relies onposition-areawithout explicit anchor pairing required when implicit anchors are unavailable.
No other clear modern-web-guidance regressions stood out in the UI diff scan (240 TSX files); remaining patterns largely follow existing extension conventions.
Sent by Cursor Automation: Modern web guidance
| alignItems={BoxAlignItems.Center} | ||
| justifyContent={BoxJustifyContent.Between} | ||
| gap={3} | ||
| <div // NOSONAR: hosts a nested tooltip trigger that a native <button> cannot contain; keyboard support is implemented below |
There was a problem hiding this comment.
Nested interactive controls (accessibility): This row is exposed as a single control (role="button" via ButtonBase asChild), but RampsQuoteDisplay renders a nested <button> for the warning tooltip trigger when showWarningIcon is set.
Interactive elements must not contain other interactive elements. Screen readers and keyboard users get ambiguous focus targets, and HTML validity checks fail.
Suggested direction: Keep the tooltip trigger outside the row activation control (e.g. sibling layout), or make the row a non-interactive container with two separate focusable controls (primary row action + warning trigger), rather than wrapping both in one button-like surface.
| onMouseLeave: handlePointerLeave, | ||
| })} | ||
| > | ||
| <button |
There was a problem hiding this comment.
Accessible name (accessibility): This trigger is icon-only and has no aria-label or visible text. Every interactive control needs an accessible name; reuse the tooltip copy or a short i18n string (e.g. “Quote unavailable, show details”).
| onClick={(event) => event.stopPropagation()} | ||
| onKeyDown={(event) => event.stopPropagation()} | ||
| data-testid="ramps-quote-display-warning-tooltip" | ||
| className="m-0 max-w-[250px] rounded-lg border border-border-muted bg-background-default p-4 text-text-default shadow-md [position-area:bottom]" |
There was a problem hiding this comment.
Native tooltip positioning (interest-triggered tooltips): Positioning uses only [position-area:bottom]. For popover="hint" + interestfor, use explicit anchor pairing when implicit anchors are unsupported: unique anchor-name on the trigger, position-anchor on the popover, anchor() insets, and a position-try fallback (e.g. flip-block). Without that, the native path can misplace the hint in browsers that support Interest Invokers but not implicit anchor positioning.


🚀 v13.51.0 Testing & Release Quality Process
Hi Team,
As part of our new MetaMask Release Quality Process, here’s a quick overview of the key processes, testing strategies, and milestones to ensure a smooth and high-quality deployment.
📋 Key Processes
Testing Strategy
Conduct regression and exploratory testing for your functional areas, including automated and manual tests for critical workflows.
Focus on exploratory testing across the wallet, prioritize high-impact areas, and triage any Sentry errors found during testing.
Validate new functionalities and provide feedback to support release monitoring.
GitHub Signoff
Issue Resolution
Cherry-Picking Criteria
🗓️ Timeline and Milestones
✅ Signoff Checklist
Each team is responsible for signing off via GitHub. Use the checkbox below to track signoff completion:
Team sign-off checklist
This process is a major step forward in ensuring release stability and quality. Let’s stay aligned and make this release a success! 🚀
Feel free to reach out if you have questions or need clarification.
Many thanks in advance
Reference