Repository: MetaMask/metamask-extension
Pull request #31564: test: Migrate accounts e2e tests to Typescript and Page object modal
Author: login: chloeYue
Labels: name: team-qa
description: QA team
name: release-12.18.0
description: Issue or pull request that will be included in release 12.18.0
Created: 2025-04-03T14:15:58Z | Merged: 2025-04-10T18:05:51Z

<!--
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**

Create related functions and migrate following e2e tests files to Typescript and Page object modal.
```
test/e2e/tests/account/account-details.spec.js
test/e2e/tests/account/incremental-security.spec.js
```
This PR is the final step in completing the migration of all e2e tests in `test/e2e/tests/account/` folder to POM

[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/31396?quickstart=1)

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MMQA-363

## **Manual testing steps**

Tests should pass and be robust

## **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.


Diff:
diff --git a/test/e2e/constants.ts b/test/e2e/constants.ts
index 36de7ebb366f..55ad689a9239 100644
--- a/test/e2e/constants.ts
+++ b/test/e2e/constants.ts
@@ -109,3 +109,6 @@ export const MOCK_CUSTOMIZED_REMOTE_FEATURE_FLAGS = {
     value: 'valueA',
   },
 };
+
+/* The password for the wallet used in e2e tests*/
+export const WALLET_PASSWORD = 'correct horse battery staple';
diff --git a/test/e2e/page-objects/pages/dialog/account-details-modal.ts b/test/e2e/page-objects/pages/dialog/account-details-modal.ts
index 0dbb2e0f87d7..4250ef85ed24 100644
--- a/test/e2e/page-objects/pages/dialog/account-details-modal.ts
+++ b/test/e2e/page-objects/pages/dialog/account-details-modal.ts
@@ -1,10 +1,19 @@
+import { tEn } from '../../../../lib/i18n-helpers';
+import { LavaDomeDebug } from '@lavamoat/lavadome-core';
 import { Driver } from '../../../webdriver/driver';
+import { WALLET_PASSWORD } from '../../../constants';
 
 class AccountDetailsModal {
   private driver: Driver;
 
   private readonly accountAddressText = '.qr-code__address-segments';
 
+  private readonly accountAuthenticateInput =
+    '#account-details-authenticate';
+
+  private readonly accountPrivateKeyText =
+    '[data-testid="account-details-key"]';
+
   private readonly accountQrCodeAddress = '.qr-code__address-segments';
 
   private readonly accountQrCodeImage = '.qr-code__wrapper';
@@ -20,6 +29,16 @@ class AccountDetailsModal {
 
   private readonly editableLabelInput = '[data-testid="editable-input"] input';
 
+  private readonly errorMessageForIncorrectPassword = {
+    css: '.mm-help-text',
+    text: 'Incorrect Password.',
+  };
+
+  private readonly holdToRevealPrivateKeyButton = {
+    text: tEn('holdToRevealPrivateKey'),
+    tag: 'span',
+  };
+
   private readonly saveAccountLabelButton =
     '[data-testid="save-account-label-input"]';
 
@@ -79,6 +98,37 @@ class AccountDetailsModal {
     return accountAddress;
   }
 
+  /**
+   * Reveal the private key of the account and verify it is correct in account details modal.
+   *
+   * @param expectedPrivateKey - The expected private key to verify.
+   * @param password - The password to authenticate with. Defaults to the default wallet password.
+   * @param expectedPasswordError - Whether to expect a password error. Defaults to false.
+   */
+  async revealPrivateKeyAndVerify({expectedPrivateKey, password = WALLET_PASSWORD, expectedPasswordError = false}): Promise<void> {
+    console.log(
+      `Reveal private key and verify it is correct in account details modal`,
+    );
+    await this.driver.clickElement(this.showPrivateKeyButton);
+    await this.driver.fill(this.accountAuthenticateInput, password);
+    await this.driver.press(this.accountAuthenticateInput, this.driver.Key.ENTER);
+    if (expectedPasswordError) {
+      await this.driver.waitForSelector(this.errorMessageForIncorrectPassword);
+      await this.driver.assertElementNotPresent(this.holdToRevealPrivateKeyButton);
+    } else {
+      await this.driver.holdMouseDownOnElement(
+        this.holdToRevealPrivateKeyButton,
+        2000,
+      );
+      // Verify the private key is expected
+      await this.driver.wait(async () => {
+        const privateKey = await this.driver.findElement(this.accountPrivateKeyText);
+        const displayedPrivateKey = LavaDomeDebug.stripDistractionFromText(await privateKey.getText());
+        return displayedPrivateKey === expectedPrivateKey;
+      });
+    }
+  }
+
   /**
    * Check that the correct address is displayed in the account details modal.
    *
diff --git a/test/e2e/page-objects/pages/header-navbar.ts b/test/e2e/page-objects/pages/header-navbar.ts
index 74273681c598..3a5c2ebe39a3 100644
--- a/test/e2e/page-objects/pages/header-navbar.ts
+++ b/test/e2e/page-objects/pages/header-navbar.ts
@@ -53,6 +53,10 @@ class HeaderNavbar {
     console.log('Header navbar is loaded');
   }
 
+  async clickAddressCopyButton(): Promise<void> {
+    await this.driver.clickElement(this.copyAddressButton);
+  }
+
   async lockMetaMask(): Promise<void> {
     await this.openThreeDotMenu();
     await this.driver.clickElement(this.lockMetaMaskButton);
diff --git a/test/e2e/page-objects/pages/home/homepage.ts b/test/e2e/page-objects/pages/home/homepage.ts
index 7965272124a7..98ae189ffb86 100644
--- a/test/e2e/page-objects/pages/home/homepage.ts
+++ b/test/e2e/page-objects/pages/home/homepage.ts
@@ -13,6 +13,16 @@ class HomePage {
     testId: 'account-overview__activity-tab',
   };
 
+  private readonly backupSecretRecoveryPhraseButton = {
+    text: 'Back up now',
+    css: '.home-notification__accept-button',
+  };
+
+  private readonly backupSecretRecoveryPhraseNotification = {
+    text: 'Back up your Secret Recovery Phrase to keep your wallet and funds secure.',
+    css: '.home-notification__text',
+  };
+
   protected readonly balance: string =
     '[data-testid="eth-overview__primary-currency"]';
 
@@ -103,6 +113,12 @@ class HomePage {
     await this.driver.clickElement(this.activityTab);
   }
 
+  async goToBackupSRPPage(): Promise<void> {
+    console.log(`Go to backup secret recovery phrase on homepage`);
+    await this.driver.waitForSelector(this.backupSecretRecoveryPhraseNotification);
+    await this.driver.clickElement(this.backupSecretRecoveryPhraseButton);
+  }
+
   async goToNftTab(): Promise<void> {
     console.log(`Go to NFT tab on homepage`);
     await this.driver.clickElement(this.nftTab);
@@ -151,6 +167,11 @@ class HomePage {
     });
   }
 
+  async check_backupReminderIsNotDisplayed(): Promise<void> {
+    console.log('Check backup reminder is not displayed on homepage');
+    await this.driver.assertElementNotPresent(this.backupSecretRecoveryPhraseNotification);
+  }
+
   async check_basicFunctionalityOffWarnigMessageIsDisplayed(): Promise<void> {
     console.log(
       'Check if basic functionality off warning message is displayed on homepage',
diff --git a/test/e2e/page-objects/pages/onboarding/secure-wallet-page.ts b/test/e2e/page-objects/pages/onboarding/secure-wallet-page.ts
index 3a2e75671dc6..a9f88745d8fb 100644
--- a/test/e2e/page-objects/pages/onboarding/secure-wallet-page.ts
+++ b/test/e2e/page-objects/pages/onboarding/secure-wallet-page.ts
@@ -3,6 +3,11 @@ import { Driver } from '../../../webdriver/driver';
 class SecureWalletPage {
   private driver: Driver;
 
+  private readonly confirmPasswordButton = {
+    text: 'Confirm',
+    tag: 'button',
+  };
+
   private readonly confirmRecoveryPhraseButton =
     '[data-testid="recovery-phrase-confirm"]';
 
@@ -11,6 +16,8 @@ class SecureWalletPage {
     tag: 'h2',
   };
 
+  private readonly passwordInput = '#account-details-authenticate';
+
   private readonly recoveryPhraseChips =
     '[data-testid="recovery-phrase-chips"]';
 
@@ -40,6 +47,17 @@ class SecureWalletPage {
     tag: 'h2',
   };
 
+  private readonly skipAccountSecurityMessage = {
+    text: 'Skip account security?',
+    tag: 'h3',
+  };
+
+  private readonly skipSRPBackupCheckbox =
+    '[data-testid="skip-srp-backup-popover-checkbox"]';
+
+  private readonly skipSRPBackupConfirmButton =
+    '[data-testid="skip-srp-backup"]';
+
   private readonly writeDownSecretRecoveryPhraseMessage = {
     text: 'Write down your Secret Recovery Phrase',
     tag: 'h2',
@@ -66,12 +84,22 @@ class SecureWalletPage {
     console.log('Secure wallet page is loaded');
   }
 
-  async revealAndConfirmSRP(): Promise<void> {
+  /**
+   * Reveal and confirm SRP on secure wallet page during onboarding
+   * @param needEnterPassword - Whether to enter the password
+   */
+  async revealAndConfirmSRP(
+    needEnterPassword: string = '',
+  ): Promise<void> {
     console.log(
       'Reveal and confirm SRP on secure wallet page during onboarding',
     );
     // click secure my wallet button to reveal SRP
     await this.driver.clickElement(this.secureWalletButton);
+    if (needEnterPassword) {
+      await this.driver.fill(this.passwordInput, needEnterPassword);
+      await this.driver.clickElement(this.confirmPasswordButton);
+    }
     await this.driver.waitForMultipleSelectors([
       this.writeDownSecretRecoveryPhraseMessage,
       this.revealSecretRecoveryPhraseButton,
@@ -128,6 +156,16 @@ class SecureWalletPage {
     }, this.driver.timeout);
     await this.driver.clickElement(this.recoveryPhraseNextButton);
   }
+
+  async skipSRPBackup(): Promise<void> {
+    console.log('Skip SRP backup on secure wallet page during onboarding');
+    await this.driver.clickElement(this.secureWalletLaterButton);
+    await this.driver.waitForSelector(this.skipAccountSecurityMessage);
+    await this.driver.clickElement(this.skipSRPBackupCheckbox);
+    await this.driver.clickElementAndWaitToDisappear(
+      this.skipSRPBackupConfirmButton,
+    );
+  }
 }
 
 export default SecureWalletPage;
diff --git a/test/e2e/page-objects/pages/test-dapp-send-eth-with-private-key.ts b/test/e2e/page-objects/pages/test-dapp-send-eth-with-private-key.ts
new file mode 100644
index 000000000000..00d5c150b10f
--- /dev/null
+++ b/test/e2e/page-objects/pages/test-dapp-send-eth-with-private-key.ts
@@ -0,0 +1,65 @@
+import { Driver } from '../../webdriver/driver';
+import { DAPP_URL } from '../../constants';
+
+class TestDappSendEthWithPrivateKey {
+  private readonly driver: Driver;
+
+  private readonly addressInput = '#address';
+
+  private readonly sendEthWithPrivateKeyButton = '#send';
+
+  private readonly successMessage = { css: '#success', text: 'Success' };
+
+  constructor(driver: Driver) {
+    this.driver = driver;
+  }
+
+  async check_pageIsLoaded(): Promise<void> {
+    try {
+      await this.driver.waitForMultipleSelectors([
+        this.addressInput,
+        this.sendEthWithPrivateKeyButton,
+      ]);
+    } catch (e) {
+      console.log('Timeout while waiting for Test Dapp send eth with private key page to be loaded', e);
+      throw e;
+    }
+    console.log('Test Dapp send eth with private key page is loaded');
+  }
+
+  /**
+   * Open the test dapp individual request page.
+   *
+   * @param options - The options for opening the test dapp page.
+   * @param options.contractAddress - The contract address to open the dapp with. Defaults to null.
+   * @param options.url - The URL of the dapp. Defaults to DAPP_URL.
+   * @returns A promise that resolves when the new page is opened.
+   */
+  async openTestDappSendEthWithPrivateKey({
+    contractAddress = null,
+    url = DAPP_URL,
+  }: {
+    contractAddress?: string | null;
+    url?: string;
+  } = {}): Promise<void> {
+    const dappUrl = contractAddress
+      ? `${url}/?contract=${contractAddress}`
+      : url;
+    await this.driver.openNewPage(dappUrl);
+  }
+
+  /**
+   * Sends ETH by pasting recipient address and clicking send. Waits for success.
+   */
+  async pasteAddressAndSendEthWithPrivateKey() {
+    console.log('Paste address and send eth with private key on test dapp');
+    await this.driver.pasteFromClipboardIntoField(this.addressInput);
+    await this.driver.clickElement(this.sendEthWithPrivateKeyButton);
+    await this.driver.waitForSelector(
+      this.successMessage,
+      { timeout: 15000 },
+    );
+  }
+}
+
+export default TestDappSendEthWithPrivateKey;
\ No newline at end of file
diff --git a/test/e2e/tests/account/account-details.spec.js b/test/e2e/tests/account/account-details.spec.js
deleted file mode 100644
index bfd90d5359e8..000000000000
--- a/test/e2e/tests/account/account-details.spec.js
+++ /dev/null
@@ -1,198 +0,0 @@
-const { strict: assert } = require('assert');
-const { LavaDomeDebug } = require('@lavamoat/lavadome-core');
-const { withFixtures, unlockWallet } = require('../../helpers');
-const FixtureBuilder = require('../../fixture-builder');
-const { tEn } = require('../../../lib/i18n-helpers');
-
-describe('Show account details', function () {
-  const PASSWORD = 'correct horse battery staple';
-  const wrongPassword = 'test test test test';
-
-  async function revealPrivateKey(driver, useAccountMenu = true) {
-    if (useAccountMenu) {
-      await driver.clickElement('[data-testid="account-menu-icon"]');
-      await driver.clickElement(
-        '[data-testid="account-list-item-menu-button"]',
-      );
-      await driver.clickElement('[data-testid="account-list-menu-details"]');
-    } else {
-      // Global Menu
-      await driver.clickElement('[data-testid="account-options-menu-button"]');
-      await driver.clickElement('[data-testid="account-list-menu-details"]');
-    }
-    await driver.clickElement({ css: 'button', text: tEn('showPrivateKey') });
-
-    await driver.fill('#account-details-authenticate', PASSWORD);
-    await driver.press('#account-details-authenticate', driver.Key.ENTER);
-
-    await driver.holdMouseDownOnElement(
-      {
-        text: tEn('holdToRevealPrivateKey'),
-        tag: 'span',
-      },
-      2000,
-    );
-
-    const keyContainer = await driver.findElement(
-      '[data-testid="account-details-key"]',
-    );
-    const key = await keyContainer.getText();
-    return LavaDomeDebug.stripDistractionFromText(key);
-  }
-
-  it('should show the QR code for the account', async function () {
-    await withFixtures(
-      {
-        fixtures: new FixtureBuilder().build(),
-        title: this.test.fullTitle(),
-      },
-      async ({ driver }) => {
-        await unlockWallet(driver);
-
-        await driver.clickElement('[data-testid="account-menu-icon"]');
-        await driver.clickElement(
-          '[data-testid="account-list-item-menu-button"]',
-        );
-        await driver.clickElement('[data-testid="account-list-menu-details"');
-
-        await driver.waitForSelector('.qr-code__wrapper');
-      },
-    );
-  });
-
-  it('should show the correct private key from account menu', async function () {
-    await withFixtures(
-      {
-        fixtures: new FixtureBuilder().build(),
-        title: this.test.fullTitle(),
-      },
-      async ({ driver }) => {
-        await unlockWallet(driver);
-
-        const key = await revealPrivateKey(driver);
-        assert.equal(
-          key,
-          '7c9529a67102755b7e6102d6d950ac5d5863c98713805cec576b945b15b71eac',
-        );
-      },
-    );
-  });
-
-  it('should show the correct private key for an unselected account from account menu', async function () {
-    await withFixtures(
-      {
-        fixtures: new FixtureBuilder().build(),
-        title: this.test.fullTitle(),
-      },
-      async ({ driver }) => {
-        await unlockWallet(driver);
-
-        // Create and focus on different account
-        await driver.clickElement('[data-testid="account-menu-icon"]');
-        await driver.clickElement(
-          '[data-testid="multichain-account-menu-popover-action-button"]',
-        );
-        await driver.clickElement(
-          '[data-testid="multichain-account-menu-popover-add-account"]',
-        );
-        await driver.fill('[placeholder="Account 2"]', '2nd account');
-        await driver.clickElement({ text: tEn('addAccount'), tag: 'button' });
-        await driver.assertElementNotPresent({
-          text: tEn('create'),
-          tag: 'button',
-        });
-
-        const key = await revealPrivateKey(driver);
-        assert.equal(
-          key,
-          '7c9529a67102755b7e6102d6d950ac5d5863c98713805cec576b945b15b71eac',
-        );
-      },
-    );
-  });
-
-  it('should show the correct private key from global menu', async function () {
-    await withFixtures(
-      {
-        fixtures: new FixtureBuilder().build(),
-        title: this.test.fullTitle(),
-      },
-      async ({ driver }) => {
-        await unlockWallet(driver);
-
-        const key = await revealPrivateKey(driver, false);
-        assert.equal(
-          key,
-          '7c9529a67102755b7e6102d6d950ac5d5863c98713805cec576b945b15b71eac',
-        );
-      },
-    );
-  });
-
-  it('should show the correct private key for a second account from global menu', async function () {
-    await withFixtures(
-      {
-        fixtures: new FixtureBuilder().build(),
-        title: this.test.fullTitle(),
-      },
-      async ({ driver }) => {
-        await unlockWallet(driver);
-
-        // Create and focus on different account
-        await driver.clickElement('[data-testid="account-menu-icon"]');
-        await driver.clickElement(
-          '[data-testid="multichain-account-menu-popover-action-button"]',
-        );
-        await driver.clickElement(
-          '[data-testid="multichain-account-menu-popover-add-account"]',
-        );
-        await driver.fill('[placeholder="Account 2"]', '2nd account');
-        await driver.clickElement({ text: tEn('addAccount'), tag: 'button' });
-        await driver.assertElementNotPresent({
-          text: tEn('create'),
-          tag: 'button',
-        });
-
-        const key = await revealPrivateKey(driver, false);
-        assert.equal(
-          key,
-          'f444f52ea41e3a39586d7069cb8e8233e9f6b9dea9cbb700cce69ae860661cc8',
-        );
-      },
-    );
-  });
-
-  it('should not reveal private key when password is incorrect', async function () {
-    await withFixtures(
-      {
-        fixtures: new FixtureBuilder().build(),
-        title: this.test.fullTitle(),
-        ignoredConsoleErrors: ['Error in verifying password'],
-      },
-      async ({ driver }) => {
-        await unlockWallet(driver);
-
-        // Attempt to reveal private key from account menu
-        await driver.clickElement('[data-testid="account-menu-icon"]');
-        await driver.clickElement(
-          '[data-testid="account-list-item-menu-button"]',
-        );
-        await driver.clickElement('[data-testid="account-list-menu-details"]');
-        await driver.clickElement({
-          css: 'button',
-          text: tEn('showPrivateKey'),
-        });
-
-        // Enter incorrect password
-        await driver.fill('#account-details-authenticate', wrongPassword);
-        await driver.press('#account-details-authenticate', driver.Key.ENTER);
-
-        // Display error when password is incorrect
-        await driver.waitForSelector({
-          css: '.mm-help-text',
-          text: 'Incorrect Password.',
-        });
-      },
-    );
-  });
-});
diff --git a/test/e2e/tests/account/account-details.spec.ts b/test/e2e/tests/account/account-details.spec.ts
new file mode 100644
index 000000000000..d8286fd6a144
--- /dev/null
+++ b/test/e2e/tests/account/account-details.spec.ts
@@ -0,0 +1,148 @@
+import { withFixtures } from '../../helpers';
+import FixtureBuilder from '../../fixture-builder';
+import { ACCOUNT_TYPE } from '../../constants';
+import AccountDetailsModal from '../../page-objects/pages/dialog/account-details-modal';
+import AccountListPage from '../../page-objects/pages/account-list-page';
+import HeaderNavbar from '../../page-objects/pages/header-navbar';
+import { loginWithBalanceValidation } from '../../page-objects/flows/login.flow';
+
+describe('Show account details', function () {
+  const wrongPassword = 'test test test test';
+
+  it('should show the correct private key from account menu', async function () {
+    await withFixtures(
+      {
+        fixtures: new FixtureBuilder().build(),
+        title: this.test?.fullTitle(),
+      },
+      async ({ driver }) => {
+        await loginWithBalanceValidation(driver);
+        await new HeaderNavbar(driver).openAccountMenu();
+        const accountListPage = new AccountListPage(driver);
+        await accountListPage.check_pageIsLoaded();
+        await accountListPage.openAccountDetailsModal('Account 1');
+        const accountDetailsModal = new AccountDetailsModal(driver);
+        await accountDetailsModal.check_pageIsLoaded();
+        await accountDetailsModal.revealPrivateKeyAndVerify(
+          {
+            expectedPrivateKey: '7c9529a67102755b7e6102d6d950ac5d5863c98713805cec576b945b15b71eac',
+          },
+        );
+      },
+    );
+  });
+
+  it('should show the correct private key for an unselected account from account menu', async function () {
+    await withFixtures(
+      {
+        fixtures: new FixtureBuilder().build(),
+        title: this.test?.fullTitle(),
+      },
+      async ({ driver }) => {
+        await loginWithBalanceValidation(driver);
+        await new HeaderNavbar(driver).openAccountMenu();
+        const accountListPage = new AccountListPage(driver);
+        await accountListPage.check_pageIsLoaded();
+
+        // Create and focus on different account
+        await accountListPage.addAccount({
+          accountType: ACCOUNT_TYPE.Ethereum,
+          accountName: '2nd account',
+        });
+        const headerNavbar = new HeaderNavbar(driver);
+        await headerNavbar.check_accountLabel('2nd account');
+
+        // Reveal private key for Account 1
+        await headerNavbar.openAccountMenu();
+        await accountListPage.check_pageIsLoaded();
+        await accountListPage.openAccountDetailsModal('Account 1');
+        const accountDetailsModal = new AccountDetailsModal(driver);
+        await accountDetailsModal.check_pageIsLoaded();
+        await accountDetailsModal.revealPrivateKeyAndVerify(
+          {
+            expectedPrivateKey: '7c9529a67102755b7e6102d6d950ac5d5863c98713805cec576b945b15b71eac',
+          },
+        );
+      },
+    );
+  });
+
+  it('should show the correct private key from global menu', async function () {
+    await withFixtures(
+      {
+        fixtures: new FixtureBuilder().build(),
+        title: this.test?.fullTitle(),
+      },
+      async ({ driver }) => {
+        await loginWithBalanceValidation(driver);
+        await new HeaderNavbar(driver).openAccountDetailsModal();
+        const accountDetailsModal = new AccountDetailsModal(driver);
+        await accountDetailsModal.check_pageIsLoaded();
+        await accountDetailsModal.revealPrivateKeyAndVerify(
+          {
+            expectedPrivateKey: '7c9529a67102755b7e6102d6d950ac5d5863c98713805cec576b945b15b71eac',
+          },
+        );
+      },
+    );
+  });
+
+  it('should show the correct private key for a second account from global menu', async function () {
+    await withFixtures(
+      {
+        fixtures: new FixtureBuilder().build(),
+        title: this.test?.fullTitle(),
+      },
+      async ({ driver }) => {
+        await loginWithBalanceValidation(driver);
+        await new HeaderNavbar(driver).openAccountMenu();
+        const accountListPage = new AccountListPage(driver);
+        await accountListPage.check_pageIsLoaded();
+
+        // Create and focus on second account
+        await accountListPage.addAccount({
+          accountType: ACCOUNT_TYPE.Ethereum,
+          accountName: '2nd account',
+        });
+        const headerNavbar = new HeaderNavbar(driver);
+        await headerNavbar.check_accountLabel('2nd account');
+
+        // Reveal private key for Account 2
+        await headerNavbar.openAccountDetailsModal();
+        const accountDetailsModal = new AccountDetailsModal(driver);
+        await accountDetailsModal.check_pageIsLoaded();
+        await accountDetailsModal.revealPrivateKeyAndVerify(
+          {
+            expectedPrivateKey: 'f444f52ea41e3a39586d7069cb8e8233e9f6b9dea9cbb700cce69ae860661cc8',
+          },
+        );
+      },
+    );
+  });
+
+  it('should not reveal private key when password is incorrect', async function () {
+    await withFixtures(
+      {
+        fixtures: new FixtureBuilder().build(),
+        title: this.test?.fullTitle(),
+        ignoredConsoleErrors: ['Error in verifying password'],
+      },
+      async ({ driver }) => {
+        await loginWithBalanceValidation(driver);
+        await new HeaderNavbar(driver).openAccountMenu();
+        const accountListPage = new AccountListPage(driver);
+        await accountListPage.check_pageIsLoaded();
+        await accountListPage.openAccountDetailsModal('Account 1');
+        const accountDetailsModal = new AccountDetailsModal(driver);
+        await accountDetailsModal.check_pageIsLoaded();
+
+        // Attempt to reveal private key from account menu with a wrong password and verify the error message
+        await accountDetailsModal.revealPrivateKeyAndVerify({
+          expectedPrivateKey: 'f444f52ea41e3a39586d7069cb8e8233e9f6b9dea9cbb700cce69ae860661cc8',
+          password: wrongPassword,
+          expectedPasswordError: true,
+        });
+      },
+    );
+  });
+});
diff --git a/test/e2e/tests/account/incremental-security.spec.js b/test/e2e/tests/account/incremental-security.spec.js
deleted file mode 100644
index 5b48cb699a88..000000000000
--- a/test/e2e/tests/account/incremental-security.spec.js
+++ /dev/null
@@ -1,165 +0,0 @@
-const { strict: assert } = require('assert');
-const { withFixtures, openDapp } = require('../../helpers');
-const FixtureBuilder = require('../../fixture-builder');
-
-const WALLET_PASSWORD = 'correct horse battery staple';
-
-describe('Incremental Security', function () {
-  it('Back up Secret Recovery Phrase from backup reminder', async function () {
-    await withFixtures(
-      {
-        dapp: true,
-        fixtures: new FixtureBuilder({ onboarding: true }).build(),
-        title: this.test.fullTitle(),
-        dappPath: 'send-eth-with-private-key-test',
-      },
-      async ({ driver, localNodes }) => {
-        // Seed Account
-        await localNodes[0].setAccountBalance(
-          '0x0Cc5261AB8cE458dc977078A3623E2BaDD27afD3',
-          '0x100000000000000000000',
-        );
-        await driver.navigate();
-        // agree to terms of use
-        await driver.clickElement('[data-testid="onboarding-terms-checkbox"]');
-
-        // welcome
-        await driver.clickElement('[data-testid="onboarding-create-wallet"]');
-
-        // metrics
-        await driver.clickElement('[data-testid="metametrics-no-thanks"]');
-
-        // create password
-        await driver.fill(
-          '[data-testid="create-password-new"]',
-          'correct horse battery staple',
-        );
-        await driver.fill(
-          '[data-testid="create-password-confirm"]',
-          'correct horse battery staple',
-        );
-        await driver.clickElement('[data-testid="create-password-terms"]');
-        await driver.clickElement('[data-testid="create-password-wallet"]');
-
-        // secure wallet later
-        await driver.clickElement('[data-testid="secure-wallet-later"]');
-        await driver.clickElement(
-          '[data-testid="skip-srp-backup-popover-checkbox"]',
-        );
-        await driver.clickElement('[data-testid="skip-srp-backup"]');
-
-        // complete
-        await driver.clickElement('[data-testid="onboarding-complete-done"]');
-
-        // pin extension
-        await driver.clickElement('[data-testid="pin-extension-next"]');
-        await driver.clickElement('[data-testid="pin-extension-done"]');
-
-        // open account menu
-        await driver.clickElement('[data-testid="account-menu-icon"]');
-        await driver.clickElement(
-          '.multichain-account-list-item--selected [data-testid="account-list-item-menu-button"]',
-        );
-        await driver.clickElement('[data-testid="account-list-menu-details"');
-
-        const outerSegment = await driver.findElement(
-          '.qr-code__address-segments',
-        );
-        const publicAddress = await outerSegment.getText();
-
-        // wait for account modal to be visible
-        await driver.findVisibleElement(
-          '[data-testid="account-details-modal"]',
-        );
-        await driver.clickElement('header button[aria-label="Close"]');
-
-        // wait for account modal to be removed from DOM
-        await driver.assertElementNotPresent(
-          '[data-testid="account-details-modal"]',
-        );
-
-        // send to current account from dapp with different provider
-        const windowHandles = await driver.getAllWindowHandles();
-        const extension = windowHandles[0];
-
-        // switched to Dapp
-        await openDapp(driver);
-
-        // sends eth to the current account
-        await driver.fill('#address', publicAddress);
-        await driver.clickElement('#send');
-
-        await driver.waitForSelector(
-          { css: '#success', text: 'Success' },
-          { timeout: 15000 },
-        );
-
-        // switch to extension
-        await driver.switchToWindow(extension);
-
-        // should have the correct amount of eth
-        let currencyDisplay = await driver.waitForSelector({
-          css: '.currency-display-component__text',
-          text: '1',
-        });
-        let balance = await currencyDisplay.getText();
-        assert.strictEqual(balance, '1');
-
-        // backs up the Secret Recovery Phrase
-        // should show a backup reminder
-        const backupReminder = await driver.findElements({
-          xpath:
-            "//div[contains(@class, 'home-notification__text') and contains(text(), 'Back up your Secret Recovery Phrase to keep your wallet and funds secure')]",
-        });
-        assert.equal(backupReminder.length, 1);
-
-        // should take the user to the seedphrase backup screen
-        await driver.clickElement('.home-notification__accept-button');
-
-        // reveals the Secret Recovery Phrase
-        await driver.clickElement('[data-testid="secure-wallet-recommended"]');
-
-        await driver.fill('[placeholder="Password"]', WALLET_PASSWORD);
-
-        await driver.clickElement({ text: 'Confirm', tag: 'button' });
-        await driver.assertElementNotPresent(
-          '[data-testid="reveal-srp-modal"]',
-        );
-
-        const recoveryPhraseRevealButton = await driver.findClickableElement(
-          '[data-testid="recovery-phrase-reveal"]',
-        );
-        await recoveryPhraseRevealButton.click();
-
-        const chipTwo = await (
-          await driver.findElement('[data-testid="recovery-phrase-chip-2"]')
-        ).getText();
-        const chipThree = await (
-          await driver.findElement('[data-testid="recovery-phrase-chip-3"]')
-        ).getText();
-        const chipSeven = await (
-          await driver.findElement('[data-testid="recovery-phrase-chip-7"]')
-        ).getText();
-        await driver.clickElement('[data-testid="recovery-phrase-next"]');
-
-        // can retype the Secret Recovery Phrase
-        await driver.fill('[data-testid="recovery-phrase-input-2"]', chipTwo);
-        await driver.fill('[data-testid="recovery-phrase-input-3"]', chipThree);
-        await driver.fill('[data-testid="recovery-phrase-input-7"]', chipSeven);
-        await driver.clickElement('[data-testid="recovery-phrase-confirm"]');
-
-        // should have the correct amount of eth
-        currencyDisplay = await driver.waitForSelector({
-          css: '.currency-display-component__text',
-          text: '1',
-        });
-        balance = await currencyDisplay.getText();
-
-        assert.strictEqual(balance, '1');
-
-        // The previous currencyDisplay wait already serves as the guard here for the assertElementNotPresent
-        await driver.assertElementNotPresent('.backup-notification');
-      },
-    );
-  });
-});
diff --git a/test/e2e/tests/account/incremental-security.spec.ts b/test/e2e/tests/account/incremental-security.spec.ts
new file mode 100644
index 000000000000..7e9337802b99
--- /dev/null
+++ b/test/e2e/tests/account/incremental-security.spec.ts
@@ -0,0 +1,90 @@
+import { withFixtures } from '../../helpers';
+import { WALLET_PASSWORD } from '../../constants';
+import FixtureBuilder from '../../fixture-builder';
+import { Driver } from '../../webdriver/driver';
+import { Suite } from 'mocha';
+import HomePage from '../../page-objects/pages/home/homepage';
+import OnboardingCompletePage from '../../page-objects/pages/onboarding/onboarding-complete-page';
+import OnboardingMetricsPage from '../../page-objects/pages/onboarding/onboarding-metrics-page';
+import OnboardingPasswordPage from '../../page-objects/pages/onboarding/onboarding-password-page';
+import SecureWalletPage from '../../page-objects/pages/onboarding/secure-wallet-page';
+import StartOnboardingPage from '../../page-objects/pages/onboarding/start-onboarding-page';
+import TestDappSendEthWithPrivateKey from '../../page-objects/pages/test-dapp-send-eth-with-private-key';
+
+describe('Incremental Security', function (this: Suite) {
+  it('Back up Secret Recovery Phrase from backup reminder', async function () {
+    await withFixtures(
+      {
+        dapp: true,
+        fixtures: new FixtureBuilder({ onboarding: true }).build(),
+        title: this.test?.fullTitle(),
+        dappPath: 'send-eth-with-private-key-test',
+      },
+      async ({ driver, localNodes }: { driver: Driver; localNodes: any[] }) => {
+        // Seed Account
+        await localNodes[0].setAccountBalance(
+          '0x0Cc5261AB8cE458dc977078A3623E2BaDD27afD3',
+          '0x100000000000000000000',
+        );
+        await driver.navigate();
+
+        // agree to terms of use and start onboarding
+        const startOnboardingPage = new StartOnboardingPage(driver);
+        await startOnboardingPage.check_pageIsLoaded();
+        await startOnboardingPage.checkTermsCheckbox();
+        await startOnboardingPage.clickCreateWalletButton();
+
+        // skip collect metametrics
+        const onboardingMetricsPage = new OnboardingMetricsPage(driver);
+        await onboardingMetricsPage.clickNoThanksButton();
+
+        // create password
+        const onboardingPasswordPage = new OnboardingPasswordPage(driver);
+        await onboardingPasswordPage.check_pageIsLoaded();
+        await onboardingPasswordPage.createWalletPassword(WALLET_PASSWORD);
+
+        // secure wallet later
+        const secureWalletPage = new SecureWalletPage(driver);
+        await secureWalletPage.check_pageIsLoaded();
+        await secureWalletPage.skipSRPBackup();
+
+        // complete onboarding and pin extension
+        const onboardingCompletePage = new OnboardingCompletePage(driver);
+        await onboardingCompletePage.check_pageIsLoaded();
+        await onboardingCompletePage.completeOnboarding();
+
+        // copy the wallet address
+        const homePage = new HomePage(driver);
+        await homePage.check_pageIsLoaded();
+        await homePage.headerNavbar.clickAddressCopyButton();
+
+        // switched to Dapp and send eth to the current account
+        const windowHandles = await driver.getAllWindowHandles();
+        const extension = windowHandles[0];
+        const testDapp = new TestDappSendEthWithPrivateKey(driver);
+        await testDapp.openTestDappSendEthWithPrivateKey();
+        await testDapp.check_pageIsLoaded();
+        await testDapp.pasteAddressAndSendEthWithPrivateKey();
+
+        // switch back to extension and check the balance is updated
+        await driver.switchToWindow(extension);
+        await homePage.check_pageIsLoaded();
+        await homePage.check_expectedBalanceIsDisplayed('1');
+
+        // backup reminder is displayed and it directs user to the backup SRP page
+        await homePage.goToBackupSRPPage();
+        await secureWalletPage.check_pageIsLoaded();
+
+        // reveal and confirm the Secret Recovery Phrase on backup SRP page
+        await secureWalletPage.revealAndConfirmSRP(WALLET_PASSWORD);
+
+        // check the balance is correct after revealing and confirming the SRP
+        await homePage.check_pageIsLoaded();
+        await homePage.check_expectedBalanceIsDisplayed('1');
+
+        // check backup reminder is not displayed on homepage
+        await homePage.check_backupReminderIsNotDisplayed();
+      },
+    );
+  });
+});


Reviews:
user: login: benjisclowder
body: Hi @chloeYue , left two small comments. Thank you!
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T15:10:21Z
user: login: chloeYue
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T15:19:29Z
user: login: benjisclowder
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T08:06:06Z
user: login: seaona
body: Added a couple of comments. Not mandatory as it's not introduced by this PR, but for improvement. Feel free to take them or leave them for another PR
state: DISMISSED
author_association: MEMBER
submitted_at: 2025-04-10T08:23:46Z
user: login: chloeYue
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T12:56:15Z
user: login: chloeYue
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T12:56:28Z
user: login: chloeYue
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T12:58:31Z
user: login: chloeYue
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T12:59:10Z
user: login: benjisclowder
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T14:39:22Z
user: login: hjetpoluru
body: LGTM 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T16:05:18Z

Review comments:
diff_hunk: @@ -79,6 +98,37 @@ class AccountDetailsModal {
     return accountAddress;
   }
 
+  /**
+   * Reveal the private key of the account and verify it is correct in account details modal.
+   *
+   * @param expectedPrivateKey - The expected private key to verify.
+   * @param password - The password to authenticate with. Defaults to the default wallet password.
+   * @param expectedPasswordError - Whether to expect a password error. Defaults to false.
+   */
+  async revealPrivateKeyAndVerify({expectedPrivateKey, password = WALLET_PASSWORD, expectedPasswordError = false}): Promise<void> {
+    console.log(
+      `Reveal private key and verify it is correct in account details modal`,
+    );
+    await this.driver.clickElement(this.showPrivateKeyButton);
+    await this.driver.fill(this.accountAuthenticateInput, password);
+    await this.driver.press(this.accountAuthenticateInput, this.driver.Key.ENTER);
+    if (expectedPasswordError) {
+      await this.driver.waitForSelector(this.errorMessageForIncorrectPassword);
+      await this.driver.assertElementNotPresent(this.holdToRevealPrivateKeyButton);
+    } else {
+      await this.driver.holdMouseDownOnElement(
+        this.holdToRevealPrivateKeyButton,
+        2000,
+      );
+    // Verify the private key is expected
+    await this.driver.wait(async () => {
+      const privateKey = await this.driver.findElement(this.accountPrivateKeyText);
+      const displayedPrivateKey = LavaDomeDebug.stripDistractionFromText(await privateKey.getText());
+      return displayedPrivateKey === expectedPrivateKey;
+    });
+  }
path: test/e2e/page-objects/pages/dialog/account-details-modal.ts
user: login: benjisclowder
body: Hi @chloeYue , there is improper closing of the else block here at line 129, and verification code would run regardless of password error. Should we move verification inside the block at line 129? This is important because: if there is a password error, the code shouldn't attempt to verify the private key. Instead, if there is a password error, with the verification code inside the `else` block, only the error message is checked and we don't attempt to verify private key. 
created_at: 2025-04-09T15:04:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -20,6 +29,16 @@ class AccountDetailsModal {
 
   private readonly editableLabelInput = '[data-testid="editable-input"] input';
 
+  private readonly errorMessageForIncorrectPassword = {
+    css: '.mm-help-text',
+    text: 'Incorrect Password.',
+  }
path: test/e2e/page-objects/pages/dialog/account-details-modal.ts
user: login: benjisclowder
body: ```suggestion
  };
```
Missing semicolon
created_at: 2025-04-09T15:04:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -79,6 +98,37 @@ class AccountDetailsModal {
     return accountAddress;
   }
 
+  /**
+   * Reveal the private key of the account and verify it is correct in account details modal.
+   *
+   * @param expectedPrivateKey - The expected private key to verify.
+   * @param password - The password to authenticate with. Defaults to the default wallet password.
+   * @param expectedPasswordError - Whether to expect a password error. Defaults to false.
+   */
+  async revealPrivateKeyAndVerify({expectedPrivateKey, password = WALLET_PASSWORD, expectedPasswordError = false}): Promise<void> {
+    console.log(
+      `Reveal private key and verify it is correct in account details modal`,
+    );
+    await this.driver.clickElement(this.showPrivateKeyButton);
+    await this.driver.fill(this.accountAuthenticateInput, password);
+    await this.driver.press(this.accountAuthenticateInput, this.driver.Key.ENTER);
+    if (expectedPasswordError) {
+      await this.driver.waitForSelector(this.errorMessageForIncorrectPassword);
+      await this.driver.assertElementNotPresent(this.holdToRevealPrivateKeyButton);
+    } else {
+      await this.driver.holdMouseDownOnElement(
+        this.holdToRevealPrivateKeyButton,
+        2000,
+      );
+    // Verify the private key is expected
+    await this.driver.wait(async () => {
+      const privateKey = await this.driver.findElement(this.accountPrivateKeyText);
+      const displayedPrivateKey = LavaDomeDebug.stripDistractionFromText(await privateKey.getText());
+      return displayedPrivateKey === expectedPrivateKey;
+    });
+  }
path: test/e2e/page-objects/pages/dialog/account-details-modal.ts
user: login: chloeYue
body: Hello @benjisclowder ,  the closing of else block is intended behaviour.
The ` Verify the private key is expected` will only run if `expectedPasswordError` is false

created_at: 2025-04-09T15:19:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,10 +1,19 @@
+import { tEn } from '../../../../lib/i18n-helpers';
+import { LavaDomeDebug } from '@lavamoat/lavadome-core';
 import { Driver } from '../../../webdriver/driver';
+import { WALLET_PASSWORD } from '../../../helpers';
path: test/e2e/page-objects/pages/dialog/account-details-modal.ts
user: login: seaona
body: 

unrelated to the PR, but in case you want to fix it: I would add this variable in thee2e/constants.ts file and then import it from there here.
There are a couple of specs that use that, so I would gradually be updating them to use the variable in the constants file instead of the helpers one, and eventually remove this variable from helpers (together with the method that uses that)

What do you think?

created_at: 2025-04-10T08:02:22Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,104 @@
+import { withFixtures, WALLET_PASSWORD } from '../../helpers';
path: test/e2e/tests/account/incremental-security.spec.ts
user: login: seaona
body: related to my 1st comment, I would then import this from the constants file `WALLET_PASSWORD`
created_at: 2025-04-10T08:08:58Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,104 @@
+import { withFixtures, WALLET_PASSWORD } from '../../helpers';
+import FixtureBuilder from '../../fixture-builder';
+import { Driver } from '../../webdriver/driver';
+import { Suite } from 'mocha';
+import HomePage from '../../page-objects/pages/home/homepage';
+import OnboardingCompletePage from '../../page-objects/pages/onboarding/onboarding-complete-page';
+import OnboardingMetricsPage from '../../page-objects/pages/onboarding/onboarding-metrics-page';
+import OnboardingPasswordPage from '../../page-objects/pages/onboarding/onboarding-password-page';
+import SecureWalletPage from '../../page-objects/pages/onboarding/secure-wallet-page';
+import StartOnboardingPage from '../../page-objects/pages/onboarding/start-onboarding-page';
+import TestDapp from '../../page-objects/pages/test-dapp';
+
+/**
+ * Sends ETH to the current account from the dapp send-eth-with-private-key-test
+ * This dapp is only used in this test spec, so we keep the function here
+ * TODO: migrate this function to follow page object modal pattern when this dapp is used in other tests
+ */
+async function sendEthWithPrivateKey(driver: Driver) {
+  const sendEthWithPrivateKeyButton = '#send';
+  await driver.waitForSelector(sendEthWithPrivateKeyButton);
+  await driver.pasteFromClipboardIntoField('#address');
+  await driver.clickElement(sendEthWithPrivateKeyButton);
+  await driver.waitForSelector(
+    { css: '#success', text: 'Success' },
+    { timeout: 15000 },
+  );
+}
path: test/e2e/tests/account/incremental-security.spec.ts
user: login: seaona
body: mmm I would rather create a new class and add all these actions inside that class already in this PR. The reason for that is because if there's a new spec that needs to use this, we are not 100% sure a new class will be created, and given we are already migrating to POM in this PR, it might be safer to just do it here?

This might also be less confusing than now, as it seems we are opening the "regular" test dapp, but this is not the case for this spec.

What do you think?

created_at: 2025-04-10T08:18:35Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,104 @@
+import { withFixtures, WALLET_PASSWORD } from '../../helpers';
+import FixtureBuilder from '../../fixture-builder';
+import { Driver } from '../../webdriver/driver';
+import { Suite } from 'mocha';
+import HomePage from '../../page-objects/pages/home/homepage';
+import OnboardingCompletePage from '../../page-objects/pages/onboarding/onboarding-complete-page';
+import OnboardingMetricsPage from '../../page-objects/pages/onboarding/onboarding-metrics-page';
+import OnboardingPasswordPage from '../../page-objects/pages/onboarding/onboarding-password-page';
+import SecureWalletPage from '../../page-objects/pages/onboarding/secure-wallet-page';
+import StartOnboardingPage from '../../page-objects/pages/onboarding/start-onboarding-page';
+import TestDapp from '../../page-objects/pages/test-dapp';
+
+/**
+ * Sends ETH to the current account from the dapp send-eth-with-private-key-test
+ * This dapp is only used in this test spec, so we keep the function here
+ * TODO: migrate this function to follow page object modal pattern when this dapp is used in other tests
+ */
+async function sendEthWithPrivateKey(driver: Driver) {
+  const sendEthWithPrivateKeyButton = '#send';
+  await driver.waitForSelector(sendEthWithPrivateKeyButton);
+  await driver.pasteFromClipboardIntoField('#address');
+  await driver.clickElement(sendEthWithPrivateKeyButton);
+  await driver.waitForSelector(
+    { css: '#success', text: 'Success' },
+    { timeout: 15000 },
+  );
+}
+
+describe('Incremental Security', function (this: Suite) {
+  it('Back up Secret Recovery Phrase from backup reminder', async function () {
+    await withFixtures(
+      {
+        dapp: true,
+        fixtures: new FixtureBuilder({ onboarding: true }).build(),
+        title: this.test?.fullTitle(),
+        dappPath: 'send-eth-with-private-key-test',
+      },
+      async ({ driver, localNodes }: { driver: Driver; localNodes: any[] }) => {
+        // Seed Account
+        await localNodes[0].setAccountBalance(
+          '0x0Cc5261AB8cE458dc977078A3623E2BaDD27afD3',
+          '0x100000000000000000000',
+        );
+        await driver.navigate();
+
+        // agree to terms of use and start onboarding
+        const startOnboardingPage = new StartOnboardingPage(driver);
+        await startOnboardingPage.check_pageIsLoaded();
+        await startOnboardingPage.checkTermsCheckbox();
+        await startOnboardingPage.clickCreateWalletButton();
+
+        // skip collect metametrics
+        const onboardingMetricsPage = new OnboardingMetricsPage(driver);
+        await onboardingMetricsPage.clickNoThanksButton();
+
+        // create password
+        const onboardingPasswordPage = new OnboardingPasswordPage(driver);
+        await onboardingPasswordPage.check_pageIsLoaded();
+        await onboardingPasswordPage.createWalletPassword(WALLET_PASSWORD);
+
+        // secure wallet later
+        const secureWalletPage = new SecureWalletPage(driver);
+        await secureWalletPage.check_pageIsLoaded();
+        await secureWalletPage.skipSRPBackup();
+
+        // complete onboarding and pin extension
+        const onboardingCompletePage = new OnboardingCompletePage(driver);
+        await onboardingCompletePage.check_pageIsLoaded();
+        await onboardingCompletePage.completeOnboarding();
+
+        // copy the wallet address
+        const homePage = new HomePage(driver);
+        await homePage.check_pageIsLoaded();
+        await homePage.headerNavbar.clickAddressCopyButton();
+
+        // switched to Dapp and send eth to the current account
+        const windowHandles = await driver.getAllWindowHandles();
+        const extension = windowHandles[0];
+        const testDapp = new TestDapp(driver);
+        await testDapp.openTestDappPage();
path: test/e2e/tests/account/incremental-security.spec.ts
user: login: seaona
body: instead of using the testDapp class, we'll then use the sendEthWithPrivKeyDapp class, so it results in a less confusing test
created_at: 2025-04-10T08:22:25Z
author_association: MEMBER
diff_hunk: @@ -1,10 +1,19 @@
+import { tEn } from '../../../../lib/i18n-helpers';
+import { LavaDomeDebug } from '@lavamoat/lavadome-core';
 import { Driver } from '../../../webdriver/driver';
+import { WALLET_PASSWORD } from '../../../helpers';
path: test/e2e/page-objects/pages/dialog/account-details-modal.ts
user: login: chloeYue
body: Agree ! we should better organize to minimize the helpers file. addressed in commit [1748dc2](https://github.com/MetaMask/metamask-extension/pull/31564/commits/1748dc219a857e552ffb5507cc47318c5f1065a3)
created_at: 2025-04-10T12:56:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,104 @@
+import { withFixtures, WALLET_PASSWORD } from '../../helpers';
path: test/e2e/tests/account/incremental-security.spec.ts
user: login: chloeYue
body: Agree ! addressed in commit [1748dc2](https://github.com/MetaMask/metamask-extension/pull/31564/commits/1748dc219a857e552ffb5507cc47318c5f1065a3)
created_at: 2025-04-10T12:56:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,104 @@
+import { withFixtures, WALLET_PASSWORD } from '../../helpers';
+import FixtureBuilder from '../../fixture-builder';
+import { Driver } from '../../webdriver/driver';
+import { Suite } from 'mocha';
+import HomePage from '../../page-objects/pages/home/homepage';
+import OnboardingCompletePage from '../../page-objects/pages/onboarding/onboarding-complete-page';
+import OnboardingMetricsPage from '../../page-objects/pages/onboarding/onboarding-metrics-page';
+import OnboardingPasswordPage from '../../page-objects/pages/onboarding/onboarding-password-page';
+import SecureWalletPage from '../../page-objects/pages/onboarding/secure-wallet-page';
+import StartOnboardingPage from '../../page-objects/pages/onboarding/start-onboarding-page';
+import TestDapp from '../../page-objects/pages/test-dapp';
+
+/**
+ * Sends ETH to the current account from the dapp send-eth-with-private-key-test
+ * This dapp is only used in this test spec, so we keep the function here
+ * TODO: migrate this function to follow page object modal pattern when this dapp is used in other tests
+ */
+async function sendEthWithPrivateKey(driver: Driver) {
+  const sendEthWithPrivateKeyButton = '#send';
+  await driver.waitForSelector(sendEthWithPrivateKeyButton);
+  await driver.pasteFromClipboardIntoField('#address');
+  await driver.clickElement(sendEthWithPrivateKeyButton);
+  await driver.waitForSelector(
+    { css: '#success', text: 'Success' },
+    { timeout: 15000 },
+  );
+}
path: test/e2e/tests/account/incremental-security.spec.ts
user: login: chloeYue
body: yeah initially i did research, as only this spec uses the specific test dapp for send-eth-with-private-key, so i left it here in spec file. but makes sense to do it better, so i created a new class page and addressed in commit [1748dc2](https://github.com/MetaMask/metamask-extension/pull/31564/commits/1748dc219a857e552ffb5507cc47318c5f1065a3)
created_at: 2025-04-10T12:58:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,104 @@
+import { withFixtures, WALLET_PASSWORD } from '../../helpers';
+import FixtureBuilder from '../../fixture-builder';
+import { Driver } from '../../webdriver/driver';
+import { Suite } from 'mocha';
+import HomePage from '../../page-objects/pages/home/homepage';
+import OnboardingCompletePage from '../../page-objects/pages/onboarding/onboarding-complete-page';
+import OnboardingMetricsPage from '../../page-objects/pages/onboarding/onboarding-metrics-page';
+import OnboardingPasswordPage from '../../page-objects/pages/onboarding/onboarding-password-page';
+import SecureWalletPage from '../../page-objects/pages/onboarding/secure-wallet-page';
+import StartOnboardingPage from '../../page-objects/pages/onboarding/start-onboarding-page';
+import TestDapp from '../../page-objects/pages/test-dapp';
+
+/**
+ * Sends ETH to the current account from the dapp send-eth-with-private-key-test
+ * This dapp is only used in this test spec, so we keep the function here
+ * TODO: migrate this function to follow page object modal pattern when this dapp is used in other tests
+ */
+async function sendEthWithPrivateKey(driver: Driver) {
+  const sendEthWithPrivateKeyButton = '#send';
+  await driver.waitForSelector(sendEthWithPrivateKeyButton);
+  await driver.pasteFromClipboardIntoField('#address');
+  await driver.clickElement(sendEthWithPrivateKeyButton);
+  await driver.waitForSelector(
+    { css: '#success', text: 'Success' },
+    { timeout: 15000 },
+  );
+}
+
+describe('Incremental Security', function (this: Suite) {
+  it('Back up Secret Recovery Phrase from backup reminder', async function () {
+    await withFixtures(
+      {
+        dapp: true,
+        fixtures: new FixtureBuilder({ onboarding: true }).build(),
+        title: this.test?.fullTitle(),
+        dappPath: 'send-eth-with-private-key-test',
+      },
+      async ({ driver, localNodes }: { driver: Driver; localNodes: any[] }) => {
+        // Seed Account
+        await localNodes[0].setAccountBalance(
+          '0x0Cc5261AB8cE458dc977078A3623E2BaDD27afD3',
+          '0x100000000000000000000',
+        );
+        await driver.navigate();
+
+        // agree to terms of use and start onboarding
+        const startOnboardingPage = new StartOnboardingPage(driver);
+        await startOnboardingPage.check_pageIsLoaded();
+        await startOnboardingPage.checkTermsCheckbox();
+        await startOnboardingPage.clickCreateWalletButton();
+
+        // skip collect metametrics
+        const onboardingMetricsPage = new OnboardingMetricsPage(driver);
+        await onboardingMetricsPage.clickNoThanksButton();
+
+        // create password
+        const onboardingPasswordPage = new OnboardingPasswordPage(driver);
+        await onboardingPasswordPage.check_pageIsLoaded();
+        await onboardingPasswordPage.createWalletPassword(WALLET_PASSWORD);
+
+        // secure wallet later
+        const secureWalletPage = new SecureWalletPage(driver);
+        await secureWalletPage.check_pageIsLoaded();
+        await secureWalletPage.skipSRPBackup();
+
+        // complete onboarding and pin extension
+        const onboardingCompletePage = new OnboardingCompletePage(driver);
+        await onboardingCompletePage.check_pageIsLoaded();
+        await onboardingCompletePage.completeOnboarding();
+
+        // copy the wallet address
+        const homePage = new HomePage(driver);
+        await homePage.check_pageIsLoaded();
+        await homePage.headerNavbar.clickAddressCopyButton();
+
+        // switched to Dapp and send eth to the current account
+        const windowHandles = await driver.getAllWindowHandles();
+        const extension = windowHandles[0];
+        const testDapp = new TestDapp(driver);
+        await testDapp.openTestDappPage();
path: test/e2e/tests/account/incremental-security.spec.ts
user: login: chloeYue
body: agree to reduce confusion! addressed in commit [1748dc2](https://github.com/MetaMask/metamask-extension/pull/31564/commits/1748dc219a857e552ffb5507cc47318c5f1065a3)
created_at: 2025-04-10T12:59:10Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-04-03T14:16:11Z
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-03T15:25:23Z
body: <details><summary>Builds ready [47b92a4]</summary><ul><li>builds: <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/builds/metamask-chrome-12.15.0.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/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/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/builds-flask/metamask-flask-chrome-12.15.0-flask.0.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/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/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/builds-test/metamask-chrome-12.15.0.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/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/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/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/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/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/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/build-viz/index.html">Build System</a></li>
<li>bundle size: <a href="https://diuv6g5fj9pvx.cloudfront.net/metamask-extension/14246026555/bundle-size/bundle_size.json">Bundle Size Stats</a></li>
<li>user-actions-benchmark: <a href="https://diuv6g5fj9pvx.cloudfront.net/metamask-extension/14246026555/benchmarks/benchmark-chrome-browserify-userActions.json">User Actions Stats</a></li>
<li>storybook: <a href="https://diuv6g5fj9pvx.cloudfront.net/metamask-extension/14246026555/storybook-build/index.html">Storybook</a></li>
<li>typescript migration: <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/ts-migration-dashboard/index.html">Dashboard</a></li>
<li><a href="https://app.circleci.com/pipelines/github/MetaMask/metamask-extension/jobs/4721788/artifacts/">all CircleCI artifacts</a></li>
<li><details>
       <summary>bundle viz:</summary>
       <ul><li>background: <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/background-0.html">0</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/background-1.html">1</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/background-2.html">2</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/background-3.html">3</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/background-4.html">4</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/background-5.html">5</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/background-6.html">6</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/background-7.html">7</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/background-8.html">8</a></li><li>common: <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/common-0.html">0</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/common-1.html">1</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/common-2.html">2</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/common-3.html">3</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/common-4.html">4</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/common-5.html">5</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/common-6.html">6</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/common-7.html">7</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/common-8.html">8</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/common-9.html">9</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/common-10.html">10</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/common-11.html">11</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/common-12.html">12</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/common-13.html">13</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/common-14.html">14</a></li><li>ui: <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/ui-0.html">0</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/ui-1.html">1</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/ui-2.html">2</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/ui-3.html">3</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/ui-4.html">4</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/ui-5.html">5</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/ui-6.html">6</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/ui-7.html">7</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/ui-8.html">8</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/ui-9.html">9</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/ui-10.html">10</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/ui-11.html">11</a>, <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/ui-12.html">12</a></li><li>content-script: <a href="https://output.circle-artifacts.com/output/job/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/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/2c99cb3b-e62c-4a1d-a5ca-cfef9ed7977f/artifacts/0/build-artifacts/source-map-explorer/offscreen-0.html">0</a></li></ul>
     </details></li></ul></details>

<details><summary>UI Startup Metrics (1207 ± 54 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">1207</td><td align="right">1094</td><td align="right">1359</td><td align="right">54</td><td align="right">1245</td><td align="right">1297</td></tr><tr><td>load</td><td align="right">1053</td><td align="right">931</td><td align="right">1217</td><td align="right">60</td><td align="right">932</td><td align="right">993</td></tr><tr><td>domContentLoaded</td><td align="right">1047</td><td align="right">921</td><td align="right">1204</td><td align="right">61</td><td align="right">926</td><td align="right">986</td></tr><tr><td>domInteractive</td><td align="right">17</td><td align="right">13</td><td align="right">69</td><td align="right">8</td><td align="right">16</td><td align="right">28</td></tr><tr><td>firstPaint</td><td align="right">790</td><td align="right">153</td><td align="right">1214</td><td align="right">395</td><td align="right">248</td><td align="right">984</td></tr><tr><td>backgroundConnect</td><td align="right">10</td><td align="right">6</td><td align="right">29</td><td align="right">4</td><td align="right">9</td><td align="right">10</td></tr><tr><td>firstReactRender</td><td align="right">22</td><td align="right">14</td><td align="right">128</td><td align="right">14</td><td align="right">20</td><td align="right">43</td></tr><tr><td>getState</td><td align="right">11</td><td align="right">4</td><td align="right">33</td><td align="right">7</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">798</td><td align="right">668</td><td align="right">937</td><td align="right">60</td><td align="right">837</td><td align="right">888</td></tr><tr><td>setupStore</td><td align="right">9</td><td align="right">4</td><td align="right">26</td><td align="right">4</td><td align="right">7</td><td align="right">9</td></tr><tr><td rowspan="11">Webpack</td><td rowspan="11">Home</td><td>uiStartup</td><td align="right">2175</td><td align="right">1773</td><td align="right">2634</td><td align="right">187</td><td align="right">2297</td><td align="right">2390</td></tr><tr><td>load</td><td align="right">1688</td><td align="right">1381</td><td align="right">2128</td><td align="right">148</td><td align="right">1793</td><td align="right">1900</td></tr><tr><td>domContentLoaded</td><td align="right">1682</td><td align="right">1377</td><td align="right">2124</td><td align="right">147</td><td align="right">1788</td><td align="right">1894</td></tr><tr><td>domInteractive</td><td align="right">18</td><td align="right">13</td><td align="right">70</td><td align="right">12</td><td align="right">15</td><td align="right">53</td></tr><tr><td>firstPaint</td><td align="right">167</td><td align="right">65</td><td align="right">313</td><td align="right">56</td><td align="right">228</td><td align="right">75</td></tr><tr><td>backgroundConnect</td><td align="right">34</td><td align="right">12</td><td align="right">292</td><td align="right">30</td><td align="right">34</td><td align="right">66</td></tr><tr><td>firstReactRender</td><td align="right">199</td><td align="right">55</td><td align="right">354</td><td align="right">112</td><td align="right">64</td><td align="right">94</td></tr><tr><td>getState</td><td align="right">13</td><td align="right">4</td><td align="right">248</td><td align="right">24</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">4</td><td align="right">5</td></tr><tr><td>loadScripts</td><td align="right">1673</td><td align="right">1373</td><td align="right">2121</td><td align="right">146</td><td align="right">1781</td><td align="right">1884</td></tr><tr><td>setupStore</td><td align="right">42</td><td align="right">6</td><td align="right">312</td><td align="right">75</td><td align="right">269</td><td align="right">7</td></tr><tr><td rowspan="22">Firefox</td><td rowspan="11">Browserify</td><td rowspan="11">Home</td><td>uiStartup</td><td align="right">1351</td><td align="right">1196</td><td align="right">1931</td><td align="right">133</td><td align="right">1377</td><td align="right">1661</td></tr><tr><td>load</td><td align="right">1211</td><td align="right">1053</td><td align="right">1764</td><td align="right">128</td><td align="right">1240</td><td align="right">1493</td></tr><tr><td>domContentLoaded</td><td align="right">1211</td><td align="right">1053</td><td align="right">1764</td><td align="right">128</td><td align="right">1240</td><td align="right">1493</td></tr><tr><td>domInteractive</td><td align="right">97</td><td align="right">35</td><td align="right">190</td><td align="right">24</td><td align="right">90</td><td align="right">98</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">24</td><td align="right">16</td><td align="right">92</td><td align="right">11</td><td align="right">23</td><td align="right">51</td></tr><tr><td>firstReactRender</td><td align="right">22</td><td align="right">19</td><td align="right">31</td><td align="right">2</td><td align="right">22</td><td align="right">29</td></tr><tr><td>getState</td><td align="right">6</td><td align="right">3</td><td align="right">13</td><td align="right">2</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">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">1188</td><td align="right">1037</td><td align="right">1739</td><td align="right">126</td><td align="right">1219</td><td align="right">1463</td></tr><tr><td>setupStore</td><td align="right">6</td><td align="right">4</td><td align="right">18</td><td align="right">2</td><td align="right">6</td><td align="right">7</td></tr><tr><td rowspan="11">Webpack</td><td rowspan="11">Home</td><td>uiStartup</td><td align="right">1598</td><td align="right">1360</td><td align="right">2207</td><td align="right">168</td><td align="right">1645</td><td align="right">2038</td></tr><tr><td>load</td><td align="right">1374</td><td align="right">1169</td><td align="right">1984</td><td align="right">155</td><td align="right">1425</td><td align="right">1803</td></tr><tr><td>domContentLoaded</td><td align="right">1373</td><td align="right">1169</td><td align="right">1984</td><td align="right">155</td><td align="right">1425</td><td align="right">1803</td></tr><tr><td>domInteractive</td><td align="right">97</td><td align="right">44</td><td align="right">172</td><td align="right">22</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">26</td><td align="right">18</td><td align="right">75</td><td align="right">8</td><td align="right">27</td><td align="right">45</td></tr><tr><td>firstReactRender</td><td align="right">37</td><td align="right">30</td><td align="right">56</td><td align="right">5</td><td align="right">39</td><td align="right">48</td></tr><tr><td>getState</td><td align="right">9</td><td align="right">4</td><td align="right">42</td><td align="right">6</td><td align="right">8</td><td align="right">9</td></tr><tr><td>initialActions</td><td align="right">1</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">1350</td><td align="right">1150</td><td align="right">1962</td><td align="right">155</td><td align="right">1402</td><td align="right">1777</td></tr><tr><td>setupStore</td><td align="right">8</td><td align="right">5</td><td align="right">24</td><td align="right">3</td><td align="right">8</td><td align="right">9</td></tr></tbody></table></details>

<details><summary>Bundle size diffs [🚀 Bundle size reduced!]</summary><ul><li>background: -121 Bytes (0%)</li>
<li>ui: 8.8 KiB (0.13%)</li>
<li>common: -869 Bytes (-0.01%)</li></ul></details>


author_association: COLLABORATOR
user: login: metamaskbot
created_at: 2025-04-09T19:47:45Z
body: <details><summary>Builds ready [901aed1]</summary><ul><li>builds: <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/builds/metamask-chrome-12.15.2.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/builds-mv2/metamask-firefox-12.15.2.zip">firefox</a></li>
<li>builds (flask): <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/builds-flask/metamask-flask-chrome-12.15.2-flask.0.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/builds-flask-mv2/metamask-flask-firefox-12.15.2-flask.0.zip">firefox</a></li>
<li>builds (test): <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/builds-test/metamask-chrome-12.15.2.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/builds-test-mv2/metamask-firefox-12.15.2.zip">firefox</a></li>
<li>builds (test-flask): <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/builds-test-flask/metamask-flask-chrome-12.15.2-flask.0.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/builds-test-flask-mv2/metamask-flask-firefox-12.15.2-flask.0.zip">firefox</a></li>
<li>build viz: <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/build-viz/index.html">Build System</a></li>
<li>bundle size: <a href="https://diuv6g5fj9pvx.cloudfront.net/metamask-extension/14361952727/bundle-size/bundle_size.json">Bundle Size Stats</a></li>
<li>user-actions-benchmark: <a href="https://diuv6g5fj9pvx.cloudfront.net/metamask-extension/14361952727/benchmarks/benchmark-chrome-browserify-userActions.json">User Actions Stats</a></li>
<li>storybook: <a href="https://diuv6g5fj9pvx.cloudfront.net/metamask-extension/14361952727/storybook-build/index.html">Storybook</a></li>
<li>typescript migration: <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/ts-migration-dashboard/index.html">Dashboard</a></li>
<li><a href="https://app.circleci.com/pipelines/github/MetaMask/metamask-extension/jobs/4751307/artifacts/">all CircleCI artifacts</a></li>
<li><details>
       <summary>bundle viz:</summary>
       <ul><li>background: <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/background-0.html">0</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/background-1.html">1</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/background-2.html">2</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/background-3.html">3</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/background-4.html">4</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/background-5.html">5</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/background-6.html">6</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/background-7.html">7</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/background-8.html">8</a></li><li>common: <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/common-0.html">0</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/common-1.html">1</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/common-2.html">2</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/common-3.html">3</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/common-4.html">4</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/common-5.html">5</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/common-6.html">6</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/common-7.html">7</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/common-8.html">8</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/common-9.html">9</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/common-10.html">10</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/common-11.html">11</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/common-12.html">12</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/common-13.html">13</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/common-14.html">14</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/common-15.html">15</a></li><li>ui: <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/ui-0.html">0</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/ui-1.html">1</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/ui-2.html">2</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/ui-3.html">3</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/ui-4.html">4</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/ui-5.html">5</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/ui-6.html">6</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/ui-7.html">7</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/ui-8.html">8</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/ui-9.html">9</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/ui-10.html">10</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/ui-11.html">11</a>, <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/ui-12.html">12</a></li><li>content-script: <a href="https://output.circle-artifacts.com/output/job/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/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/b1c62d0e-54eb-408a-9a32-8b310fee3b4c/artifacts/0/build-artifacts/source-map-explorer/offscreen-0.html">0</a></li></ul>
     </details></li></ul></details>

<details><summary>UI Startup Metrics (1259 ± 62 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">1259</td><td align="right">1152</td><td align="right">1505</td><td align="right">62</td><td align="right">1300</td><td align="right">1366</td></tr><tr><td>load</td><td align="right">1099</td><td align="right">953</td><td align="right">1325</td><td align="right">67</td><td align="right">1152</td><td align="right">953</td></tr><tr><td>domContentLoaded</td><td align="right">1093</td><td align="right">945</td><td align="right">1319</td><td align="right">66</td><td align="right">1149</td><td align="right">947</td></tr><tr><td>domInteractive</td><td align="right">18</td><td align="right">14</td><td align="right">62</td><td align="right">7</td><td align="right">17</td><td align="right">32</td></tr><tr><td>firstPaint</td><td align="right">753</td><td align="right">83</td><td align="right">1335</td><td align="right">437</td><td align="right">237</td><td align="right">83</td></tr><tr><td>backgroundConnect</td><td align="right">9</td><td align="right">7</td><td align="right">19</td><td align="right">2</td><td align="right">9</td><td align="right">10</td></tr><tr><td>firstReactRender</td><td align="right">20</td><td align="right">13</td><td align="right">55</td><td align="right">6</td><td align="right">20</td><td align="right">34</td></tr><tr><td>getState</td><td align="right">13</td><td align="right">5</td><td align="right">34</td><td align="right">8</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">4</td><td align="right">0</td><td align="right">0</td><td align="right">1</td></tr><tr><td>loadScripts</td><td align="right">842</td><td align="right">697</td><td align="right">1048</td><td align="right">64</td><td align="right">879</td><td align="right">952</td></tr><tr><td>setupStore</td><td align="right">8</td><td align="right">5</td><td align="right">18</td><td align="right">3</td><td align="right">7</td><td align="right">9</td></tr><tr><td rowspan="11">Webpack</td><td rowspan="11">Home</td><td>uiStartup</td><td align="right">2219</td><td align="right">1799</td><td align="right">2630</td><td align="right">187</td><td align="right">2340</td><td align="right">2482</td></tr><tr><td>load</td><td align="right">1756</td><td align="right">1380</td><td align="right">2183</td><td align="right">172</td><td align="right">1842</td><td align="right">2062</td></tr><tr><td>domContentLoaded</td><td align="right">1745</td><td align="right">1375</td><td align="right">2153</td><td align="right">164</td><td align="right">1837</td><td align="right">2048</td></tr><tr><td>domInteractive</td><td align="right">18</td><td align="right">13</td><td align="right">64</td><td align="right">13</td><td align="right">15</td><td align="right">56</td></tr><tr><td>firstPaint</td><td align="right">170</td><td align="right">65</td><td align="right">326</td><td align="right">53</td><td align="right">221</td><td align="right">75</td></tr><tr><td>backgroundConnect</td><td align="right">50</td><td align="right">12</td><td align="right">358</td><td align="right">68</td><td align="right">41</td><td align="right">70</td></tr><tr><td>firstReactRender</td><td align="right">157</td><td align="right">54</td><td align="right">414</td><td align="right">109</td><td align="right">62</td><td align="right">93</td></tr><tr><td>getState</td><td align="right">36</td><td align="right">4</td><td align="right">316</td><td align="right">74</td><td align="right">6</td><td align="right">9</td></tr><tr><td>initialActions</td><td align="right">3</td><td align="right">1</td><td align="right">8</td><td align="right">1</td><td align="right">3</td><td align="right">6</td></tr><tr><td>loadScripts</td><td align="right">1735</td><td align="right">1366</td><td align="right">2149</td><td align="right">160</td><td align="right">1826</td><td align="right">2016</td></tr><tr><td>setupStore</td><td align="right">20</td><td align="right">7</td><td align="right">176</td><td align="right">24</td><td align="right">7</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">1400</td><td align="right">1224</td><td align="right">1783</td><td align="right">108</td><td align="right">1467</td><td align="right">1627</td></tr><tr><td>load</td><td align="right">1246</td><td align="right">1080</td><td align="right">1522</td><td align="right">99</td><td align="right">1301</td><td align="right">1440</td></tr><tr><td>domContentLoaded</td><td align="right">1246</td><td align="right">1080</td><td align="right">1521</td><td align="right">99</td><td align="right">1301</td><td align="right">1440</td></tr><tr><td>domInteractive</td><td align="right">100</td><td align="right">38</td><td align="right">179</td><td align="right">27</td><td align="right">91</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">30</td><td align="right">17</td><td align="right">242</td><td align="right">24</td><td align="right">30</td><td align="right">47</td></tr><tr><td>firstReactRender</td><td align="right">24</td><td align="right">19</td><td align="right">49</td><td align="right">5</td><td align="right">24</td><td align="right">38</td></tr><tr><td>getState</td><td align="right">8</td><td align="right">4</td><td align="right">77</td><td align="right">8</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">0</td><td align="right">1</td></tr><tr><td>loadScripts</td><td align="right">1218</td><td align="right">1057</td><td align="right">1489</td><td align="right">96</td><td align="right">1271</td><td align="right">1411</td></tr><tr><td>setupStore</td><td align="right">7</td><td align="right">4</td><td align="right">37</td><td align="right">4</td><td align="right">6</td><td align="right">8</td></tr><tr><td rowspan="11">Webpack</td><td rowspan="11">Home</td><td>uiStartup</td><td align="right">1581</td><td align="right">1363</td><td align="right">2010</td><td align="right">130</td><td align="right">1650</td><td align="right">1854</td></tr><tr><td>load</td><td align="right">1358</td><td align="right">1177</td><td align="right">1770</td><td align="right">119</td><td align="right">1424</td><td align="right">1630</td></tr><tr><td>domContentLoaded</td><td align="right">1357</td><td align="right">1176</td><td align="right">1770</td><td align="right">119</td><td align="right">1424</td><td align="right">1630</td></tr><tr><td>domInteractive</td><td align="right">98</td><td align="right">54</td><td align="right">414</td><td align="right">38</td><td align="right">91</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">27</td><td align="right">18</td><td align="right">82</td><td align="right">10</td><td align="right">27</td><td align="right">46</td></tr><tr><td>firstReactRender</td><td align="right">36</td><td align="right">29</td><td align="right">66</td><td align="right">6</td><td align="right">38</td><td align="right">46</td></tr><tr><td>getState</td><td align="right">11</td><td align="right">4</td><td align="right">286</td><td align="right">28</td><td align="right">8</td><td align="right">9</td></tr><tr><td>initialActions</td><td align="right">1</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">1334</td><td align="right">1155</td><td align="right">1750</td><td align="right">119</td><td align="right">1402</td><td align="right">1605</td></tr><tr><td>setupStore</td><td align="right">8</td><td align="right">5</td><td align="right">39</td><td align="right">4</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-10T13:33:01Z
body: <details><summary>Builds ready [1748dc2]</summary><ul><li>builds: <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/builds/metamask-chrome-12.15.2.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/builds-mv2/metamask-firefox-12.15.2.zip">firefox</a></li>
<li>builds (flask): <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/builds-flask/metamask-flask-chrome-12.15.2-flask.0.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/builds-flask-mv2/metamask-flask-firefox-12.15.2-flask.0.zip">firefox</a></li>
<li>builds (test): <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/builds-test/metamask-chrome-12.15.2.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/builds-test-mv2/metamask-firefox-12.15.2.zip">firefox</a></li>
<li>builds (test-flask): <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/builds-test-flask/metamask-flask-chrome-12.15.2-flask.0.zip">chrome</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/builds-test-flask-mv2/metamask-flask-firefox-12.15.2-flask.0.zip">firefox</a></li>
<li>build viz: <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/build-viz/index.html">Build System</a></li>
<li>bundle size: <a href="https://diuv6g5fj9pvx.cloudfront.net/metamask-extension/14380975633/bundle-size/bundle_size.json">Bundle Size Stats</a></li>
<li>user-actions-benchmark: <a href="https://diuv6g5fj9pvx.cloudfront.net/metamask-extension/14380975633/benchmarks/benchmark-chrome-browserify-userActions.json">User Actions Stats</a></li>
<li>storybook: <a href="https://diuv6g5fj9pvx.cloudfront.net/metamask-extension/14380975633/storybook-build/index.html">Storybook</a></li>
<li>typescript migration: <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/ts-migration-dashboard/index.html">Dashboard</a></li>
<li><a href="https://app.circleci.com/pipelines/github/MetaMask/metamask-extension/jobs/4757615/artifacts/">all CircleCI artifacts</a></li>
<li><details>
       <summary>bundle viz:</summary>
       <ul><li>background: <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/background-0.html">0</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/background-1.html">1</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/background-2.html">2</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/background-3.html">3</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/background-4.html">4</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/background-5.html">5</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/background-6.html">6</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/background-7.html">7</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/background-8.html">8</a></li><li>common: <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/common-0.html">0</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/common-1.html">1</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/common-2.html">2</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/common-3.html">3</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/common-4.html">4</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/common-5.html">5</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/common-6.html">6</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/common-7.html">7</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/common-8.html">8</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/common-9.html">9</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/common-10.html">10</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/common-11.html">11</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/common-12.html">12</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/common-13.html">13</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/common-14.html">14</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/common-15.html">15</a></li><li>ui: <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/ui-0.html">0</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/ui-1.html">1</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/ui-2.html">2</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/ui-3.html">3</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/ui-4.html">4</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/ui-5.html">5</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/ui-6.html">6</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/ui-7.html">7</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/ui-8.html">8</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/ui-9.html">9</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/ui-10.html">10</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/ui-11.html">11</a>, <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/ui-12.html">12</a></li><li>content-script: <a href="https://output.circle-artifacts.com/output/job/e78492ee-22bc-4738-865c-aa23e4da5863/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/e78492ee-22bc-4738-865c-aa23e4da5863/artifacts/0/build-artifacts/source-map-explorer/offscreen-0.html">0</a></li></ul>
     </details></li></ul></details>

<details><summary>UI Startup Metrics (1257 ± 58 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">1257</td><td align="right">1138</td><td align="right">1447</td><td align="right">58</td><td align="right">1293</td><td align="right">1345</td></tr><tr><td>load</td><td align="right">1095</td><td align="right">988</td><td align="right">1258</td><td align="right">55</td><td align="right">1128</td><td align="right">1201</td></tr><tr><td>domContentLoaded</td><td align="right">1090</td><td align="right">982</td><td align="right">1253</td><td align="right">55</td><td align="right">1129</td><td align="right">990</td></tr><tr><td>domInteractive</td><td align="right">18</td><td align="right">14</td><td align="right">59</td><td align="right">8</td><td align="right">18</td><td align="right">34</td></tr><tr><td>firstPaint</td><td align="right">661</td><td align="right">171</td><td align="right">1246</td><td align="right">438</td><td align="right">245</td><td align="right">293</td></tr><tr><td>backgroundConnect</td><td align="right">7</td><td align="right">4</td><td align="right">24</td><td align="right">2</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">41</td><td align="right">4</td><td align="right">20</td><td align="right">30</td></tr><tr><td>getState</td><td align="right">14</td><td align="right">5</td><td align="right">38</td><td align="right">8</td><td align="right">7</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">0</td><td align="right">1</td></tr><tr><td>loadScripts</td><td align="right">842</td><td align="right">744</td><td align="right">981</td><td align="right">53</td><td align="right">872</td><td align="right">936</td></tr><tr><td>setupStore</td><td align="right">8</td><td align="right">5</td><td align="right">22</td><td align="right">3</td><td align="right">8</td><td align="right">9</td></tr><tr><td rowspan="11">Webpack</td><td rowspan="11">Home</td><td>uiStartup</td><td align="right">2308</td><td align="right">1742</td><td align="right">2701</td><td align="right">180</td><td align="right">2422</td><td align="right">2602</td></tr><tr><td>load</td><td align="right">1837</td><td align="right">1343</td><td align="right">2345</td><td align="right">174</td><td align="right">1890</td><td align="right">2197</td></tr><tr><td>domContentLoaded</td><td align="right">1828</td><td align="right">1338</td><td align="right">2337</td><td align="right">173</td><td align="right">1879</td><td align="right">2193</td></tr><tr><td>domInteractive</td><td align="right">17</td><td align="right">12</td><td align="right">77</td><td align="right">11</td><td align="right">15</td><td align="right">49</td></tr><tr><td>firstPaint</td><td align="right">172</td><td align="right">63</td><td align="right">357</td><td align="right">62</td><td align="right">220</td><td align="right">69</td></tr><tr><td>backgroundConnect</td><td align="right">39</td><td align="right">9</td><td align="right">269</td><td align="right">42</td><td align="right">44</td><td align="right">82</td></tr><tr><td>firstReactRender</td><td align="right">184</td><td align="right">56</td><td align="right">355</td><td align="right">109</td><td align="right">59</td><td align="right">70</td></tr><tr><td>getState</td><td align="right">19</td><td align="right">4</td><td align="right">253</td><td align="right">29</td><td align="right">5</td><td align="right">9</td></tr><tr><td>initialActions</td><td align="right">3</td><td align="right">1</td><td align="right">7</td><td align="right">1</td><td align="right">4</td><td align="right">6</td></tr><tr><td>loadScripts</td><td align="right">1820</td><td align="right">1337</td><td align="right">2335</td><td align="right">168</td><td align="right">1870</td><td align="right">2191</td></tr><tr><td>setupStore</td><td align="right">26</td><td align="right">7</td><td align="right">275</td><td align="right">38</td><td align="right">47</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">1188</td><td align="right">1678</td><td align="right">103</td><td align="right">1426</td><td align="right">1554</td></tr><tr><td>load</td><td align="right">1219</td><td align="right">1041</td><td align="right">1558</td><td align="right">106</td><td align="right">1281</td><td align="right">1424</td></tr><tr><td>domContentLoaded</td><td align="right">1218</td><td align="right">1041</td><td align="right">1558</td><td align="right">106</td><td align="right">1280</td><td align="right">1424</td></tr><tr><td>domInteractive</td><td align="right">105</td><td align="right">38</td><td align="right">264</td><td align="right">30</td><td align="right">86</td><td align="right">98</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">13</td><td align="right">108</td><td align="right">10</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">51</td><td align="right">5</td><td align="right">22</td><td align="right">27</td></tr><tr><td>getState</td><td align="right">7</td><td align="right">4</td><td align="right">30</td><td align="right">4</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">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">1201</td><td align="right">1027</td><td align="right">1541</td><td align="right">107</td><td align="right">1263</td><td align="right">1408</td></tr><tr><td>setupStore</td><td align="right">6</td><td align="right">4</td><td align="right">35</td><td align="right">4</td><td align="right">6</td><td align="right">6</td></tr><tr><td rowspan="11">Webpack</td><td rowspan="11">Home</td><td>uiStartup</td><td align="right">1553</td><td align="right">1364</td><td align="right">2012</td><td align="right">132</td><td align="right">1602</td><td align="right">1893</td></tr><tr><td>load</td><td align="right">1335</td><td align="right">1173</td><td align="right">1771</td><td align="right">112</td><td align="right">1387</td><td align="right">1588</td></tr><tr><td>domContentLoaded</td><td align="right">1335</td><td align="right">1173</td><td align="right">1770</td><td align="right">112</td><td align="right">1387</td><td align="right">1588</td></tr><tr><td>domInteractive</td><td align="right">94</td><td align="right">44</td><td align="right">182</td><td align="right">25</td><td align="right">86</td><td align="right">95</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">15</td><td align="right">49</td><td align="right">6</td><td align="right">23</td><td align="right">38</td></tr><tr><td>firstReactRender</td><td align="right">36</td><td align="right">29</td><td align="right">48</td><td align="right">4</td><td align="right">39</td><td align="right">45</td></tr><tr><td>getState</td><td align="right">12</td><td align="right">4</td><td align="right">201</td><td align="right">20</td><td align="right">8</td><td align="right">9</td></tr><tr><td>initialActions</td><td align="right">1</td><td align="right">0</td><td align="right">1</td><td align="right">1</td><td align="right">1</td><td align="right">1</td></tr><tr><td>loadScripts</td><td align="right">1315</td><td align="right">1155</td><td align="right">1744</td><td align="right">111</td><td align="right">1362</td><td align="right">1563</td></tr><tr><td>setupStore</td><td align="right">9</td><td align="right">6</td><td align="right">30</td><td align="right">4</td><td align="right">8</td><td align="right">9</td></tr></tbody></table></details>


author_association: COLLABORATOR