Repository: MetaMask/metamask-extension
Pull request #31536: Jl/sip 26/wallet create session filter accounts non evm
Author: login: jiexi
Labels: name: team-wallet-api-platform-deprecated
description: DEPRECATED: please use "team-wallet-integrations" instead
Created: 2025-04-02T21:34:27Z | Merged: 2025-04-03T15:57:16Z

<!--
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**

Filters out unsupported non evm accounts (much like we currently do already for evm accounts) from the requested permissions. This replaces the current behavior which is to immediately return with an error if unsupported non EVM accounts are provided in the initial wallet_createSession request


[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/31536?quickstart=1)

## **Related issues**

Ticket: https://github.com/orgs/MetaMask/projects/146/views/6?pane=issue&itemId=104582156&issue=MetaMask%7CMetaMask-planning%7C4570

## **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.



Diff:
diff --git a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.ts b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.ts
index 7dd48e865318..8f2bef89c849 100644
--- a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.ts
+++ b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.ts
@@ -101,6 +101,7 @@ const createMockedHandler = () => {
     sessionScopes: NormalizedScopesObject;
     sessionProperties?: Record<string, Json>;
   }>;
+  const getNonEvmAccountAddresses = jest.fn().mockReturnValue([]);
   const handler = (
     request: JsonRpcRequest<Caip25Authorization> & { origin: string },
   ) =>
@@ -112,6 +113,7 @@ const createMockedHandler = () => {
       listAccounts,
       getNonEvmSupportedMethods,
       isNonEvmScopeSupported,
+      getNonEvmAccountAddresses,
     });
 
   return {
@@ -125,6 +127,7 @@ const createMockedHandler = () => {
     listAccounts,
     getNonEvmSupportedMethods,
     isNonEvmScopeSupported,
+    getNonEvmAccountAddresses,
     handler,
   };
 };
@@ -338,14 +341,63 @@ describe('wallet_createSession', () => {
     expect(listAccounts).toHaveBeenCalled();
   });
 
-  it('requests approval for account and permitted chains permission based on the supported eth accounts and eth chains from the supported scopes in the request', async () => {
-    const { handler, listAccounts, requestPermissionsForOrigin } =
+  it('gets the account addresses for non evm scopes', async () => {
+    const { handler, listAccounts, getNonEvmAccountAddresses } =
       createMockedHandler();
     listAccounts.mockReturnValue([
       { address: '0x1' },
       { address: '0x3' },
       { address: '0x4' },
     ]);
+    MockMultichain.bucketScopes
+      .mockReturnValueOnce({
+        supportedScopes: {},
+        supportableScopes: {},
+        unsupportableScopes: {},
+      })
+      .mockReturnValueOnce({
+        supportedScopes: {
+          'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp': {
+            methods: [],
+            notifications: [],
+            accounts: [
+              'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:EEivRh9T4GTLEJprEaKQyjSQzW13JRb5D7jSpvPQ8296',
+            ],
+          },
+          'solana:deadbeef': {
+            methods: [],
+            notifications: [],
+            accounts: [
+              'solana:deadbeef:EEivRh9T4GTLEJprEaKQyjSQzW13JRb5D7jSpvPQ8296',
+            ],
+          },
+        },
+        supportableScopes: {},
+        unsupportableScopes: {},
+      });
+    getNonEvmAccountAddresses.mockReturnValue([]);
+
+    await handler(baseRequest);
+
+    expect(getNonEvmAccountAddresses).toHaveBeenCalledTimes(2);
+    expect(getNonEvmAccountAddresses).toHaveBeenCalledWith(
+      'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
+    );
+    expect(getNonEvmAccountAddresses).toHaveBeenCalledWith('solana:deadbeef');
+  });
+
+  it('requests approval for account and permitted chains permission based on the supported accounts and scopes in the request', async () => {
+    const {
+      handler,
+      listAccounts,
+      requestPermissionsForOrigin,
+      getNonEvmAccountAddresses,
+    } = createMockedHandler();
+    listAccounts.mockReturnValue([
+      { address: '0x1' },
+      { address: '0x3' },
+      { address: '0x4' },
+    ]);
     MockMultichain.bucketScopes
       .mockReturnValueOnce({
         supportedScopes: {
@@ -365,10 +417,22 @@ describe('wallet_createSession', () => {
             notifications: [],
             accounts: ['eip155:2:0x1', 'eip155:2:0x3', 'eip155:2:0xdeadbeef'],
           },
+          'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp': {
+            methods: [],
+            notifications: [],
+            accounts: [
+              'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:EEivRh9T4GTLEJprEaKQyjSQzW13JRb5D7jSpvPQ8296',
+              'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:notSupported',
+            ],
+          },
         },
         supportableScopes: {},
         unsupportableScopes: {},
       });
+    getNonEvmAccountAddresses.mockReturnValue([
+      'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:EEivRh9T4GTLEJprEaKQyjSQzW13JRb5D7jSpvPQ8296',
+    ]);
+
     await handler(baseRequest);
 
     expect(requestPermissionsForOrigin).toHaveBeenCalledWith({
@@ -386,6 +450,11 @@ describe('wallet_createSession', () => {
                 'eip155:100': {
                   accounts: ['eip155:100:0x1', 'eip155:100:0x3'],
                 },
+                'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp': {
+                  accounts: [
+                    'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:EEivRh9T4GTLEJprEaKQyjSQzW13JRb5D7jSpvPQ8296',
+                  ],
+                },
               },
               isMultichainOrigin: true,
               sessionProperties: {},
diff --git a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts
index 283a07eae473..52bcdad78afa 100644
--- a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts
+++ b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts
@@ -3,7 +3,6 @@ import {
   Caip25CaveatType,
   Caip25EndowmentPermissionName,
   getEthAccounts,
-  setEthAccounts,
   bucketScopes,
   validateAndNormalizeScopes,
   Caip25Authorization,
@@ -12,24 +11,29 @@ import {
   NormalizedScopesObject,
   getSupportedScopeObjects,
   Caip25CaveatValue,
+  setPermittedAccounts,
 } from '@metamask/chain-agnostic-permission';
 import {
   invalidParams,
   RequestedPermissions,
 } from '@metamask/permission-controller';
 import {
+  CaipAccountId,
   CaipChainId,
   Hex,
   isPlainObject,
   Json,
   JsonRpcRequest,
   JsonRpcSuccess,
+  KnownCaipNamespace,
+  parseCaipAccountId,
 } from '@metamask/utils';
 import { NetworkController } from '@metamask/network-controller';
 import {
   JsonRpcEngineEndCallback,
   JsonRpcEngineNextCallback,
 } from '@metamask/json-rpc-engine';
+import { uniq } from 'lodash';
 import {
   MetaMetricsEventCategory,
   MetaMetricsEventName,
@@ -39,6 +43,7 @@ import {
 import { shouldEmitDappViewedEvent } from '../../../util';
 import { MESSAGE_TYPE } from '../../../../../../shared/constants/app';
 import { GrantedPermissions } from '../types';
+import { isEqualCaseInsensitive } from '../../../../../../shared/modules/string-utils';
 import { isKnownSessionPropertyValue } from './constants';
 
 /**
@@ -63,6 +68,7 @@ import { isKnownSessionPropertyValue } from './constants';
  * @param hooks.sendMetrics - The hook that tracks an analytics event.
  * @param hooks.getNonEvmSupportedMethods - The hook that returns the supported methods for a non EVM scope.
  * @param hooks.isNonEvmScopeSupported - The hook that returns true if a non EVM scope is supported.
+ * @param hooks.getNonEvmAccountAddresses - The hook that returns a list of CaipAccountIds that are supported for a CaipChainId.
  * @param hooks.metamaskState - The wallet state.
  * @param hooks.metamaskState.metaMetricsId - The analytics id.
  * @param hooks.metamaskState.permissionHistory - The permission history object keyed by origin.
@@ -93,6 +99,7 @@ async function walletCreateSessionHandler(
       permissionHistory: Record<string, unknown>;
       accounts: Record<string, unknown>;
     };
+    getNonEvmAccountAddresses: (scope: CaipChainId) => CaipAccountId[];
   },
 ) {
   const { origin } = req;
@@ -154,16 +161,44 @@ async function walletCreateSessionHandler(
     );
 
     // Fetch EVM accounts from native wallet keyring
-    // These addresses are lowercased already
     const existingEvmAddresses = hooks
       .listAccounts()
       .map((account) => account.address);
-    const supportedEthAccounts = getEthAccounts({
-      requiredScopes: supportedRequiredScopes,
-      optionalScopes: supportedOptionalScopes,
-    })
-      .map((address) => address.toLowerCase() as Hex)
-      .filter((address) => existingEvmAddresses.includes(address));
+
+    // TODO dry and or move to @metamask/chain-agnostic-permission
+    const requestedRequiredAccounts = Object.values(
+      supportedRequiredScopes,
+    ).flatMap((scope) => scope.accounts);
+    const requestedOptionalAccounts = Object.values(
+      supportedOptionalScopes,
+    ).flatMap((scope) => scope.accounts);
+
+    const allRequestedAccountAddresses = uniq([
+      ...requestedRequiredAccounts,
+      ...requestedOptionalAccounts,
+    ]);
+
+    const supportedRequestedAccountAddresses =
+      allRequestedAccountAddresses.filter((accountAddress) => {
+        const {
+          address,
+          chain: { namespace },
+          chainId: caipChainId,
+        } = parseCaipAccountId(accountAddress);
+        if (namespace === KnownCaipNamespace.Eip155) {
+          return existingEvmAddresses.some((existingEvmAddress) => {
+            return isEqualCaseInsensitive(address, existingEvmAddress);
+          });
+        }
+
+        const getNonEvmAccountAddressesForChainId =
+          hooks.getNonEvmAccountAddresses(caipChainId);
+        return getNonEvmAccountAddressesForChainId.some(
+          (existingCaipAddress) => {
+            return isEqualCaseInsensitive(accountAddress, existingCaipAddress);
+          },
+        );
+      });
 
     const requestedCaip25CaveatValue = {
       requiredScopes: getInternalScopesObject(supportedRequiredScopes),
@@ -172,11 +207,11 @@ async function walletCreateSessionHandler(
       sessionProperties: filteredSessionProperties,
     };
 
-    // TODO: we need to apply this same filtering generically to non-evm accounts as well!
-    const requestedCaip25CaveatValueWithSupportedEthAccounts = setEthAccounts(
-      requestedCaip25CaveatValue,
-      supportedEthAccounts,
-    );
+    const requestedCaip25CaveatValueWithSupportedAccounts =
+      setPermittedAccounts(
+        requestedCaip25CaveatValue,
+        supportedRequestedAccountAddresses,
+      );
 
     // Note that we do not verify non-evm accounts here. Instead we rely on
     // the CAIP-25 caveat validator to throw an error about the requested
@@ -190,7 +225,7 @@ async function walletCreateSessionHandler(
         caveats: [
           {
             type: Caip25CaveatType,
-            value: requestedCaip25CaveatValueWithSupportedEthAccounts,
+            value: requestedCaip25CaveatValueWithSupportedAccounts,
           },
         ],
       },
@@ -258,5 +293,6 @@ export const walletCreateSession = {
     metamaskState: true,
     getNonEvmSupportedMethods: true,
     isNonEvmScopeSupported: true,
+    getNonEvmAccountAddresses: true,
   },
 };
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index 33c66f229ec1..df847bc7635c 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -6835,6 +6835,10 @@ export default class MetamaskController extends EventEmitter {
             ...params,
             origin,
           }),
+        getNonEvmAccountAddresses: this.controllerMessenger.call.bind(
+          this.controllerMessenger,
+          'MultichainRouter:getSupportedAccounts',
+        ),
       }),
     );
 


Reviews:
user: login: adonesky1
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T14:08:39Z
user: login: adonesky1
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T14:10:40Z
user: login: adonesky1
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T14:10:59Z
user: login: adonesky1
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T14:12:24Z
user: login: adonesky1
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T14:12:53Z
user: login: adonesky1
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T15:53:54Z

Review comments:
diff_hunk: @@ -154,16 +161,46 @@ async function walletCreateSessionHandler(
     );
 
     // Fetch EVM accounts from native wallet keyring
-    // These addresses are lowercased already
     const existingEvmAddresses = hooks
       .listAccounts()
       .map((account) => account.address);
-    const supportedEthAccounts = getEthAccounts({
-      requiredScopes: supportedRequiredScopes,
-      optionalScopes: supportedOptionalScopes,
-    })
-      .map((address) => address.toLowerCase() as Hex)
-      .filter((address) => existingEvmAddresses.includes(address));
+    // do case insensitive compare!
path: app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts
user: login: adonesky1
body: ?
```suggestion
```
created_at: 2025-04-03T14:08:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -154,16 +161,46 @@ async function walletCreateSessionHandler(
     );
 
     // Fetch EVM accounts from native wallet keyring
-    // These addresses are lowercased already
     const existingEvmAddresses = hooks
       .listAccounts()
       .map((account) => account.address);
-    const supportedEthAccounts = getEthAccounts({
-      requiredScopes: supportedRequiredScopes,
-      optionalScopes: supportedOptionalScopes,
-    })
-      .map((address) => address.toLowerCase() as Hex)
-      .filter((address) => existingEvmAddresses.includes(address));
+    // do case insensitive compare!
+
+    // TODO dry and or move to @metamask/chain-agnostic-permission
+    const requiredAccounts = Object.values(supportedRequiredScopes).flatMap(
+      (scope) => scope.accounts,
+    );
+    const optionalAccounts = Object.values(supportedOptionalScopes).flatMap(
+      (scope) => scope.accounts,
+    );
+
+    const allAccountAddresses = uniq([
+      ...requiredAccounts,
+      ...optionalAccounts,
+    ]);
+
+    const supportedAccountAddresses = allAccountAddresses.filter(
+      (accountAddress) => {
+        const {
+          address,
+          chain: { namespace },
+          chainId,
path: app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts
user: login: adonesky1
body: just for clarity?
```suggestion
          chainId: caipChainId,
```
created_at: 2025-04-03T14:10:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -154,16 +161,46 @@ async function walletCreateSessionHandler(
     );
 
     // Fetch EVM accounts from native wallet keyring
-    // These addresses are lowercased already
     const existingEvmAddresses = hooks
       .listAccounts()
       .map((account) => account.address);
-    const supportedEthAccounts = getEthAccounts({
-      requiredScopes: supportedRequiredScopes,
-      optionalScopes: supportedOptionalScopes,
-    })
-      .map((address) => address.toLowerCase() as Hex)
-      .filter((address) => existingEvmAddresses.includes(address));
+    // do case insensitive compare!
+
+    // TODO dry and or move to @metamask/chain-agnostic-permission
+    const requiredAccounts = Object.values(supportedRequiredScopes).flatMap(
+      (scope) => scope.accounts,
+    );
+    const optionalAccounts = Object.values(supportedOptionalScopes).flatMap(
+      (scope) => scope.accounts,
+    );
+
+    const allAccountAddresses = uniq([
+      ...requiredAccounts,
+      ...optionalAccounts,
+    ]);
+
+    const supportedAccountAddresses = allAccountAddresses.filter(
+      (accountAddress) => {
+        const {
+          address,
+          chain: { namespace },
+          chainId,
+        } = parseCaipAccountId(accountAddress);
+        if (namespace === KnownCaipNamespace.Eip155) {
+          return existingEvmAddresses.some((existingEvmAddress) => {
+            return isEqualCaseInsensitive(address, existingEvmAddress);
+          });
+        }
+
+        const getNonEvmAccountAddressesForChainId =
+          hooks.getNonEvmAccountAddresses(chainId);
path: app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts
user: login: adonesky1
body: ```suggestion
          hooks.getNonEvmAccountAddresses(caipChainId);
```
created_at: 2025-04-03T14:10:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -154,16 +161,46 @@ async function walletCreateSessionHandler(
     );
 
     // Fetch EVM accounts from native wallet keyring
-    // These addresses are lowercased already
     const existingEvmAddresses = hooks
       .listAccounts()
       .map((account) => account.address);
-    const supportedEthAccounts = getEthAccounts({
-      requiredScopes: supportedRequiredScopes,
-      optionalScopes: supportedOptionalScopes,
-    })
-      .map((address) => address.toLowerCase() as Hex)
-      .filter((address) => existingEvmAddresses.includes(address));
+    // do case insensitive compare!
+
+    // TODO dry and or move to @metamask/chain-agnostic-permission
+    const requiredAccounts = Object.values(supportedRequiredScopes).flatMap(
+      (scope) => scope.accounts,
+    );
+    const optionalAccounts = Object.values(supportedOptionalScopes).flatMap(
+      (scope) => scope.accounts,
+    );
+
+    const allAccountAddresses = uniq([
+      ...requiredAccounts,
+      ...optionalAccounts,
+    ]);
path: app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts
user: login: adonesky1
body: ```suggestion
    const requestedRequiredAccounts = Object.values(supportedRequiredScopes).flatMap(
      (scope) => scope.accounts,
    );
    const requestedOptionalAccounts = Object.values(supportedOptionalScopes).flatMap(
      (scope) => scope.accounts,
    );

    const allRequestedAccountAddresses = uniq([
      ...requiredAccounts,
      ...optionalAccounts,
    ]);
```
created_at: 2025-04-03T14:12:24Z
author_association: CONTRIBUTOR
diff_hunk: @@ -154,16 +161,46 @@ async function walletCreateSessionHandler(
     );
 
     // Fetch EVM accounts from native wallet keyring
-    // These addresses are lowercased already
     const existingEvmAddresses = hooks
       .listAccounts()
       .map((account) => account.address);
-    const supportedEthAccounts = getEthAccounts({
-      requiredScopes: supportedRequiredScopes,
-      optionalScopes: supportedOptionalScopes,
-    })
-      .map((address) => address.toLowerCase() as Hex)
-      .filter((address) => existingEvmAddresses.includes(address));
+    // do case insensitive compare!
+
+    // TODO dry and or move to @metamask/chain-agnostic-permission
+    const requiredAccounts = Object.values(supportedRequiredScopes).flatMap(
+      (scope) => scope.accounts,
+    );
+    const optionalAccounts = Object.values(supportedOptionalScopes).flatMap(
+      (scope) => scope.accounts,
+    );
+
+    const allAccountAddresses = uniq([
+      ...requiredAccounts,
+      ...optionalAccounts,
+    ]);
+
+    const supportedAccountAddresses = allAccountAddresses.filter(
path: app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts
user: login: adonesky1
body: ```suggestion
    const supportedRequestedAccountAddresses = allAccountAddresses.filter(
```
created_at: 2025-04-03T14:12:53Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-04-02T21:34:39Z
body: **CLA Signature Action:** All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.
author_association: CONTRIBUTOR
user: login: metamaskbot
created_at: 2025-04-02T23:03:45Z
body: <details><summary>Builds ready [511ea04]</summary><ul><li>builds: <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/builds/metamask-chrome-12.15.0.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/builds-mv2/metamask-firefox-12.15.0.zip">firefox</a></li>
<li>builds (flask): <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/builds-flask/metamask-flask-chrome-12.15.0-flask.0.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/builds-flask-mv2/metamask-flask-firefox-12.15.0-flask.0.zip">firefox</a></li>
<li>builds (test): <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/builds-test/metamask-chrome-12.15.0.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/builds-test-mv2/metamask-firefox-12.15.0.zip">firefox</a></li>
<li>builds (test-flask): <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/builds-test-flask/metamask-flask-chrome-12.15.0-flask.0.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/builds-test-flask-mv2/metamask-flask-firefox-12.15.0-flask.0.zip">firefox</a></li>
<li>build viz: <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/build-viz/index.html">Build System</a></li>
<li>bundle size: <a href="https://diuv6g5fj9pvx.cloudfront.net/metamask-extension/14230812251/bundle-size/bundle_size.json">Bundle Size Stats</a></li>
<li>user-actions-benchmark: <a href="https://diuv6g5fj9pvx.cloudfront.net/metamask-extension/14230812251/benchmarks/benchmark-chrome-browserify-userActions.json">User Actions Stats</a></li>
<li>storybook: <a href="https://diuv6g5fj9pvx.cloudfront.net/metamask-extension/14230812251/storybook-build/index.html">Storybook</a></li>
<li>typescript migration: <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/ts-migration-dashboard/index.html">Dashboard</a></li>
<li><a href="https://app.circleci.com/pipelines/github/MetaMask/metamask-extension/jobs/4718472/artifacts/">all CircleCI artifacts</a></li>
<li><details>
       <summary>bundle viz:</summary>
       <ul><li>background: <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/background-0.html">0</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/background-1.html">1</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/background-2.html">2</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/background-3.html">3</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/background-4.html">4</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/background-5.html">5</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/background-6.html">6</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/background-7.html">7</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/background-8.html">8</a></li><li>common: <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/common-0.html">0</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/common-1.html">1</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/common-2.html">2</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/common-3.html">3</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/common-4.html">4</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/common-5.html">5</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/common-6.html">6</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/common-7.html">7</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/common-8.html">8</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/common-9.html">9</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/common-10.html">10</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/common-11.html">11</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/common-12.html">12</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/common-13.html">13</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/common-14.html">14</a></li><li>ui: <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/ui-0.html">0</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/ui-1.html">1</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/ui-2.html">2</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/ui-3.html">3</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/ui-4.html">4</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/ui-5.html">5</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/ui-6.html">6</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/ui-7.html">7</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/ui-8.html">8</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/ui-9.html">9</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/ui-10.html">10</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/ui-11.html">11</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/ui-12.html">12</a>, <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/ui-13.html">13</a></li><li>content-script: <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/content-script-0.html">0</a></li><li>offscreen: <a href="https://output.circle-artifacts.com/output/job/32a320e1-2f1c-4a07-a45d-f318fc50a0ad/artifacts/0/build-artifacts/source-map-explorer/offscreen-0.html">0</a></li></ul>
     </details></li></ul></details>

<details><summary>UI Startup Metrics (1267 ± 59 ms)</summary><table><thead><tr><th>Platform</th><th>BuildType</th><th>Page</th><th>Metric</th><th>Mean (ms)</th><th>Min (ms)</th><th>Max (ms)</th><th>Std Dev (ms)</th><th>P 75 (ms)</th><th>P 95 (ms)</th></tr></thead><tbody><tr><td rowspan="22">Chrome</td><td rowspan="11">Browserify</td><td rowspan="11">Home</td><td>uiStartup</td><td align="right">1267</td><td align="right">1135</td><td align="right">1420</td><td align="right">59</td><td align="right">1308</td><td align="right">1361</td></tr><tr><td>load</td><td align="right">1107</td><td align="right">984</td><td align="right">1262</td><td align="right">58</td><td align="right">1149</td><td align="right">984</td></tr><tr><td>domContentLoaded</td><td align="right">1100</td><td align="right">973</td><td align="right">1250</td><td align="right">58</td><td align="right">1145</td><td align="right">987</td></tr><tr><td>domInteractive</td><td align="right">17</td><td align="right">13</td><td align="right">35</td><td align="right">5</td><td align="right">17</td><td align="right">30</td></tr><tr><td>firstPaint</td><td align="right">808</td><td align="right">139</td><td align="right">1258</td><td align="right">426</td><td align="right">196</td><td align="right">280</td></tr><tr><td>backgroundConnect</td><td align="right">8</td><td align="right">4</td><td align="right">30</td><td align="right">5</td><td align="right">7</td><td align="right">9</td></tr><tr><td>firstReactRender</td><td align="right">20</td><td align="right">15</td><td align="right">70</td><td align="right">8</td><td align="right">20</td><td align="right">36</td></tr><tr><td>getState</td><td align="right">13</td><td align="right">4</td><td align="right">36</td><td align="right">8</td><td align="right">6</td><td align="right">8</td></tr><tr><td>initialActions</td><td align="right">0</td><td align="right">0</td><td align="right">1</td><td align="right">0</td><td align="right">0</td><td align="right">1</td></tr><tr><td>loadScripts</td><td align="right">838</td><td align="right">716</td><td align="right">987</td><td align="right">58</td><td align="right">876</td><td align="right">934</td></tr><tr><td>setupStore</td><td align="right">8</td><td align="right">5</td><td align="right">18</td><td align="right">2</td><td align="right">7</td><td align="right">8</td></tr><tr><td rowspan="11">Webpack</td><td rowspan="11">Home</td><td>uiStartup</td><td align="right">2138</td><td align="right">1691</td><td align="right">2666</td><td align="right">219</td><td align="right">2236</td><td align="right">2556</td></tr><tr><td>load</td><td align="right">1648</td><td align="right">1323</td><td align="right">2053</td><td align="right">169</td><td align="right">1754</td><td align="right">1960</td></tr><tr><td>domContentLoaded</td><td align="right">1641</td><td align="right">1320</td><td align="right">2042</td><td align="right">166</td><td align="right">1747</td><td align="right">1950</td></tr><tr><td>domInteractive</td><td align="right">17</td><td align="right">12</td><td align="right">63</td><td align="right">11</td><td align="right">14</td><td align="right">55</td></tr><tr><td>firstPaint</td><td align="right">210</td><td align="right">75</td><td align="right">1633</td><td align="right">156</td><td align="right">252</td><td align="right">85</td></tr><tr><td>backgroundConnect</td><td align="right">27</td><td align="right">10</td><td align="right">233</td><td align="right">27</td><td align="right">233</td><td align="right">75</td></tr><tr><td>firstReactRender</td><td align="right">216</td><td align="right">55</td><td align="right">369</td><td align="right">120</td><td align="right">71</td><td align="right">94</td></tr><tr><td>getState</td><td align="right">11</td><td align="right">4</td><td align="right">32</td><td align="right">5</td><td align="right">8</td><td align="right">9</td></tr><tr><td>initialActions</td><td align="right">3</td><td align="right">1</td><td align="right">6</td><td align="right">1</td><td align="right">3</td><td align="right">4</td></tr><tr><td>loadScripts</td><td align="right">1636</td><td align="right">1319</td><td align="right">2020</td><td align="right">164</td><td align="right">1744</td><td align="right">1942</td></tr><tr><td>setupStore</td><td align="right">28</td><td align="right">6</td><td align="right">305</td><td align="right">57</td><td align="right">23</td><td align="right">8</td></tr><tr><td rowspan="22">Firefox</td><td rowspan="11">Browserify</td><td rowspan="11">Home</td><td>uiStartup</td><td align="right">1357</td><td align="right">1215</td><td align="right">1939</td><td align="right">154</td><td align="right">1379</td><td align="right">1813</td></tr><tr><td>load</td><td align="right">1223</td><td align="right">1055</td><td align="right">1778</td><td align="right">148</td><td align="right">1251</td><td align="right">1642</td></tr><tr><td>domContentLoaded</td><td align="right">1222</td><td align="right">1055</td><td align="right">1778</td><td align="right">148</td><td align="right">1250</td><td align="right">1641</td></tr><tr><td>domInteractive</td><td align="right">103</td><td align="right">38</td><td align="right">193</td><td align="right">26</td><td align="right">86</td><td align="right">97</td></tr><tr><td>firstPaint</td><td align="right">NaN</td><td align="right">NaN</td><td align="right">NaN</td><td align="right">NaN</td><td align="right">NaN</td><td align="right">NaN</td></tr><tr><td>backgroundConnect</td><td align="right">19</td><td align="right">12</td><td align="right">109</td><td align="right">11</td><td align="right">19</td><td align="right">28</td></tr><tr><td>firstReactRender</td><td align="right">22</td><td align="right">18</td><td align="right">44</td><td align="right">4</td><td align="right">23</td><td align="right">28</td></tr><tr><td>getState</td><td align="right">7</td><td align="right">4</td><td align="right">28</td><td align="right">3</td><td align="right">7</td><td align="right">8</td></tr><tr><td>initialActions</td><td align="right">0</td><td align="right">0</td><td align="right">2</td><td align="right">0</td><td align="right">0</td><td align="right">1</td></tr><tr><td>loadScripts</td><td align="right">1205</td><td align="right">1033</td><td align="right">1745</td><td align="right">146</td><td align="right">1234</td><td align="right">1624</td></tr><tr><td>setupStore</td><td align="right">6</td><td align="right">4</td><td align="right">39</td><td align="right">4</td><td align="right">5</td><td align="right">7</td></tr><tr><td rowspan="11">Webpack</td><td rowspan="11">Home</td><td>uiStartup</td><td align="right">1497</td><td align="right">1309</td><td align="right">2006</td><td align="right">160</td><td align="right">1544</td><td align="right">1920</td></tr><tr><td>load</td><td align="right">1289</td><td align="right">1142</td><td align="right">1737</td><td align="right">140</td><td align="right">1333</td><td align="right">1647</td></tr><tr><td>domContentLoaded</td><td align="right">1288</td><td align="right">1141</td><td align="right">1737</td><td align="right">140</td><td align="right">1333</td><td align="right">1647</td></tr><tr><td>domInteractive</td><td align="right">93</td><td align="right">35</td><td align="right">218</td><td align="right">31</td><td align="right">88</td><td align="right">94</td></tr><tr><td>firstPaint</td><td align="right">NaN</td><td align="right">NaN</td><td align="right">NaN</td><td align="right">NaN</td><td align="right">NaN</td><td align="right">NaN</td></tr><tr><td>backgroundConnect</td><td align="right">21</td><td align="right">14</td><td align="right">65</td><td align="right">7</td><td align="right">21</td><td align="right">35</td></tr><tr><td>firstReactRender</td><td align="right">34</td><td align="right">27</td><td align="right">51</td><td align="right">4</td><td align="right">36</td><td align="right">42</td></tr><tr><td>getState</td><td align="right">9</td><td align="right">4</td><td align="right">32</td><td align="right">7</td><td align="right">8</td><td align="right">9</td></tr><tr><td>initialActions</td><td align="right">0</td><td align="right">0</td><td align="right">1</td><td align="right">0</td><td align="right">1</td><td align="right">1</td></tr><tr><td>loadScripts</td><td align="right">1270</td><td align="right">1126</td><td align="right">1722</td><td align="right">139</td><td align="right">1317</td><td align="right">1624</td></tr><tr><td>setupStore</td><td align="right">7</td><td align="right">4</td><td align="right">31</td><td align="right">3</td><td align="right">8</td><td align="right">9</td></tr></tbody></table></details>


author_association: COLLABORATOR
user: login: metamaskbot
created_at: 2025-04-03T15:55:52Z
body: <details><summary>Builds ready [25f8367]</summary><ul><li>builds: <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/builds/metamask-chrome-12.15.0.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/builds-mv2/metamask-firefox-12.15.0.zip">firefox</a></li>
<li>builds (flask): <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/builds-flask/metamask-flask-chrome-12.15.0-flask.0.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/builds-flask-mv2/metamask-flask-firefox-12.15.0-flask.0.zip">firefox</a></li>
<li>builds (test): <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/builds-test/metamask-chrome-12.15.0.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/builds-test-mv2/metamask-firefox-12.15.0.zip">firefox</a></li>
<li>builds (test-flask): <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/builds-test-flask/metamask-flask-chrome-12.15.0-flask.0.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/builds-test-flask-mv2/metamask-flask-firefox-12.15.0-flask.0.zip">firefox</a></li>
<li>build viz: <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/build-viz/index.html">Build System</a></li>
<li>bundle size: <a href="https://diuv6g5fj9pvx.cloudfront.net/metamask-extension/14246605757/bundle-size/bundle_size.json">Bundle Size Stats</a></li>
<li>user-actions-benchmark: <a href="https://diuv6g5fj9pvx.cloudfront.net/metamask-extension/14246605757/benchmarks/benchmark-chrome-browserify-userActions.json">User Actions Stats</a></li>
<li>storybook: <a href="https://diuv6g5fj9pvx.cloudfront.net/metamask-extension/14246605757/storybook-build/index.html">Storybook</a></li>
<li>typescript migration: <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/ts-migration-dashboard/index.html">Dashboard</a></li>
<li><a href="https://app.circleci.com/pipelines/github/MetaMask/metamask-extension/jobs/4721997/artifacts/">all CircleCI artifacts</a></li>
<li><details>
       <summary>bundle viz:</summary>
       <ul><li>background: <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/background-0.html">0</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/background-1.html">1</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/background-2.html">2</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/background-3.html">3</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/background-4.html">4</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/background-5.html">5</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/background-6.html">6</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/background-7.html">7</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/background-8.html">8</a></li><li>common: <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/common-0.html">0</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/common-1.html">1</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/common-2.html">2</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/common-3.html">3</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/common-4.html">4</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/common-5.html">5</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/common-6.html">6</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/common-7.html">7</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/common-8.html">8</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/common-9.html">9</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/common-10.html">10</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/common-11.html">11</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/common-12.html">12</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/common-13.html">13</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/common-14.html">14</a></li><li>ui: <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/ui-0.html">0</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/ui-1.html">1</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/ui-2.html">2</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/ui-3.html">3</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/ui-4.html">4</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/ui-5.html">5</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/ui-6.html">6</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/ui-7.html">7</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/ui-8.html">8</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/ui-9.html">9</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/ui-10.html">10</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/ui-11.html">11</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/ui-12.html">12</a>, <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/ui-13.html">13</a></li><li>content-script: <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/content-script-0.html">0</a></li><li>offscreen: <a href="https://output.circle-artifacts.com/output/job/0f937cff-9a9f-4892-922b-c32033aff970/artifacts/0/build-artifacts/source-map-explorer/offscreen-0.html">0</a></li></ul>
     </details></li></ul></details>

<details><summary>UI Startup Metrics (1212 ± 64 ms)</summary><table><thead><tr><th>Platform</th><th>BuildType</th><th>Page</th><th>Metric</th><th>Mean (ms)</th><th>Min (ms)</th><th>Max (ms)</th><th>Std Dev (ms)</th><th>P 75 (ms)</th><th>P 95 (ms)</th></tr></thead><tbody><tr><td rowspan="22">Chrome</td><td rowspan="11">Browserify</td><td rowspan="11">Home</td><td>uiStartup</td><td align="right">1212</td><td align="right">1086</td><td align="right">1361</td><td align="right">64</td><td align="right">1243</td><td align="right">1349</td></tr><tr><td>load</td><td align="right">1064</td><td align="right">954</td><td align="right">1216</td><td align="right">61</td><td align="right">1170</td><td align="right">985</td></tr><tr><td>domContentLoaded</td><td align="right">1057</td><td align="right">950</td><td align="right">1210</td><td align="right">62</td><td align="right">1183</td><td align="right">986</td></tr><tr><td>domInteractive</td><td align="right">16</td><td align="right">13</td><td align="right">41</td><td align="right">5</td><td align="right">16</td><td align="right">28</td></tr><tr><td>firstPaint</td><td align="right">763</td><td align="right">78</td><td align="right">1181</td><td align="right">405</td><td align="right">248</td><td align="right">995</td></tr><tr><td>backgroundConnect</td><td align="right">8</td><td align="right">4</td><td align="right">48</td><td align="right">6</td><td align="right">7</td><td align="right">8</td></tr><tr><td>firstReactRender</td><td align="right">18</td><td align="right">14</td><td align="right">47</td><td align="right">4</td><td align="right">18</td><td align="right">22</td></tr><tr><td>getState</td><td align="right">11</td><td align="right">4</td><td align="right">68</td><td align="right">10</td><td align="right">6</td><td align="right">8</td></tr><tr><td>initialActions</td><td align="right">0</td><td align="right">0</td><td align="right">1</td><td align="right">0</td><td align="right">0</td><td align="right">1</td></tr><tr><td>loadScripts</td><td align="right">805</td><td align="right">710</td><td align="right">968</td><td align="right">62</td><td align="right">842</td><td align="right">925</td></tr><tr><td>setupStore</td><td align="right">7</td><td align="right">5</td><td align="right">17</td><td align="right">2</td><td align="right">7</td><td align="right">8</td></tr><tr><td rowspan="11">Webpack</td><td rowspan="11">Home</td><td>uiStartup</td><td align="right">2097</td><td align="right">1683</td><td align="right">2571</td><td align="right">225</td><td align="right">2220</td><td align="right">2533</td></tr><tr><td>load</td><td align="right">1623</td><td align="right">1308</td><td align="right">1969</td><td align="right">170</td><td align="right">1729</td><td align="right">1951</td></tr><tr><td>domContentLoaded</td><td align="right">1616</td><td align="right">1305</td><td align="right">1947</td><td align="right">167</td><td align="right">1724</td><td align="right">1929</td></tr><tr><td>domInteractive</td><td align="right">17</td><td align="right">12</td><td align="right">58</td><td align="right">12</td><td align="right">14</td><td align="right">54</td></tr><tr><td>firstPaint</td><td align="right">190</td><td align="right">63</td><td align="right">509</td><td align="right">69</td><td align="right">228</td><td align="right">69</td></tr><tr><td>backgroundConnect</td><td align="right">23</td><td align="right">10</td><td align="right">77</td><td align="right">15</td><td align="right">22</td><td align="right">77</td></tr><tr><td>firstReactRender</td><td align="right">183</td><td align="right">53</td><td align="right">359</td><td align="right">115</td><td align="right">87</td><td align="right">98</td></tr><tr><td>getState</td><td align="right">9</td><td align="right">3</td><td align="right">21</td><td align="right">3</td><td align="right">8</td><td align="right">9</td></tr><tr><td>initialActions</td><td align="right">3</td><td align="right">1</td><td align="right">4</td><td align="right">1</td><td align="right">3</td><td align="right">4</td></tr><tr><td>loadScripts</td><td align="right">1612</td><td align="right">1303</td><td align="right">1926</td><td align="right">164</td><td align="right">1721</td><td align="right">1908</td></tr><tr><td>setupStore</td><td align="right">31</td><td align="right">7</td><td align="right">291</td><td align="right">65</td><td align="right">21</td><td align="right">9</td></tr><tr><td rowspan="22">Firefox</td><td rowspan="11">Browserify</td><td rowspan="11">Home</td><td>uiStartup</td><td align="right">1357</td><td align="right">1150</td><td align="right">1864</td><td align="right">150</td><td align="right">1413</td><td align="right">1701</td></tr><tr><td>load</td><td align="right">1219</td><td align="right">1028</td><td align="right">1707</td><td align="right">144</td><td align="right">1266</td><td align="right">1545</td></tr><tr><td>domContentLoaded</td><td align="right">1218</td><td align="right">1028</td><td align="right">1707</td><td align="right">144</td><td align="right">1266</td><td align="right">1545</td></tr><tr><td>domInteractive</td><td align="right">94</td><td align="right">37</td><td align="right">219</td><td align="right">27</td><td align="right">85</td><td align="right">96</td></tr><tr><td>firstPaint</td><td align="right">NaN</td><td align="right">NaN</td><td align="right">NaN</td><td align="right">NaN</td><td align="right">NaN</td><td align="right">NaN</td></tr><tr><td>backgroundConnect</td><td align="right">21</td><td align="right">13</td><td align="right">137</td><td align="right">15</td><td align="right">19</td><td align="right">29</td></tr><tr><td>firstReactRender</td><td align="right">22</td><td align="right">18</td><td align="right">35</td><td align="right">3</td><td align="right">24</td><td align="right">29</td></tr><tr><td>getState</td><td align="right">7</td><td align="right">3</td><td align="right">36</td><td align="right">3</td><td align="right">7</td><td align="right">8</td></tr><tr><td>initialActions</td><td align="right">0</td><td align="right">0</td><td align="right">2</td><td align="right">0</td><td align="right">0</td><td align="right">1</td></tr><tr><td>loadScripts</td><td align="right">1200</td><td align="right">1015</td><td align="right">1692</td><td align="right">140</td><td align="right">1248</td><td align="right">1525</td></tr><tr><td>setupStore</td><td align="right">5</td><td align="right">4</td><td align="right">20</td><td align="right">2</td><td align="right">5</td><td align="right">7</td></tr><tr><td rowspan="11">Webpack</td><td rowspan="11">Home</td><td>uiStartup</td><td align="right">1515</td><td align="right">1335</td><td align="right">2296</td><td align="right">164</td><td align="right">1559</td><td align="right">1865</td></tr><tr><td>load</td><td align="right">1305</td><td align="right">1150</td><td align="right">2078</td><td align="right">149</td><td align="right">1334</td><td align="right">1614</td></tr><tr><td>domContentLoaded</td><td align="right">1304</td><td align="right">1149</td><td align="right">2078</td><td align="right">149</td><td align="right">1333</td><td align="right">1614</td></tr><tr><td>domInteractive</td><td align="right">96</td><td align="right">37</td><td align="right">172</td><td align="right">27</td><td align="right">90</td><td align="right">97</td></tr><tr><td>firstPaint</td><td align="right">NaN</td><td align="right">NaN</td><td align="right">NaN</td><td align="right">NaN</td><td align="right">NaN</td><td align="right">NaN</td></tr><tr><td>backgroundConnect</td><td align="right">22</td><td align="right">14</td><td align="right">47</td><td align="right">7</td><td align="right">22</td><td align="right">42</td></tr><tr><td>firstReactRender</td><td align="right">35</td><td align="right">28</td><td align="right">55</td><td align="right">5</td><td align="right">37</td><td align="right">44</td></tr><tr><td>getState</td><td align="right">9</td><td align="right">4</td><td align="right">29</td><td align="right">6</td><td align="right">8</td><td align="right">9</td></tr><tr><td>initialActions</td><td align="right">0</td><td align="right">0</td><td align="right">2</td><td align="right">1</td><td align="right">1</td><td align="right">1</td></tr><tr><td>loadScripts</td><td align="right">1286</td><td align="right">1130</td><td align="right">2060</td><td align="right">148</td><td align="right">1315</td><td align="right">1594</td></tr><tr><td>setupStore</td><td align="right">8</td><td align="right">5</td><td align="right">32</td><td align="right">4</td><td align="right">8</td><td align="right">9</td></tr></tbody></table></details>


author_association: COLLABORATOR