From 3e5c0a80b5854e94781ba64cea63c21534b2e523 Mon Sep 17 00:00:00 2001
From: Charly Chevalier
Date: Tue, 17 Sep 2024 10:05:20 +0200
Subject: [PATCH 01/37] chore: update @metamask/bitcoin-wallet-snap to 0.6.0
(#27141)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
Bump the BTC Snap to version 0.6.0.
- This new release adds a warning/error dialog if any error occurs with
`btc_sendmany`.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/26701?quickstart=1)
## **Related issues**
N/A
## **Manual testing steps**
N/A
## **Screenshots/Recordings**
### **Before**
### **After**
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.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/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
---
package.json | 2 +-
yarn.lock | 10 +++++-----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/package.json b/package.json
index bd4c7f3cdd34..34a022f2d8d6 100644
--- a/package.json
+++ b/package.json
@@ -306,7 +306,7 @@
"@metamask/approval-controller": "^7.0.0",
"@metamask/assets-controllers": "^36.0.0",
"@metamask/base-controller": "^7.0.0",
- "@metamask/bitcoin-wallet-snap": "^0.5.0",
+ "@metamask/bitcoin-wallet-snap": "^0.6.0",
"@metamask/browser-passworder": "^4.3.0",
"@metamask/contract-metadata": "^2.5.0",
"@metamask/controller-utils": "^11.2.0",
diff --git a/yarn.lock b/yarn.lock
index 07f23e959624..ea8a91ae8270 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4890,10 +4890,10 @@ __metadata:
languageName: node
linkType: hard
-"@metamask/bitcoin-wallet-snap@npm:^0.5.0":
- version: 0.5.0
- resolution: "@metamask/bitcoin-wallet-snap@npm:0.5.0"
- checksum: 10/eeb2c11316d58fcd26b73c11b6c8cd6ed0c5d4beb28ae3237bc08c8100fbdde4f8e38ad3efb25c85f8a6722cfec8290bbbfee71718d54735beb86064a9e9435c
+"@metamask/bitcoin-wallet-snap@npm:^0.6.0":
+ version: 0.6.0
+ resolution: "@metamask/bitcoin-wallet-snap@npm:0.6.0"
+ checksum: 10/baf4d7a43ddb5f210437c722e90abc6a3b4056390cc1d075e1a09acb82e934db338fce36fb897560e7f9ecd8ff3fcbd4795b3076dc7243af7ac93ea5d47b63f5
languageName: node
linkType: hard
@@ -25977,7 +25977,7 @@ __metadata:
"@metamask/assets-controllers": "npm:^36.0.0"
"@metamask/auto-changelog": "npm:^2.1.0"
"@metamask/base-controller": "npm:^7.0.0"
- "@metamask/bitcoin-wallet-snap": "npm:^0.5.0"
+ "@metamask/bitcoin-wallet-snap": "npm:^0.6.0"
"@metamask/browser-passworder": "npm:^4.3.0"
"@metamask/build-utils": "npm:^3.0.0"
"@metamask/contract-metadata": "npm:^2.5.0"
From 8d3632b6eed5c143527bdcf50127d7df0f25948f Mon Sep 17 00:00:00 2001
From: Jyoti Puri
Date: Tue, 17 Sep 2024 15:17:55 +0530
Subject: [PATCH 02/37] chore: Update package @blockaid/ppom_release to version
1.5.3 (#27170)
---
package.json | 2 +-
.../__snapshots__/blockaid-banner-alert.test.js.snap | 12 ++++++------
yarn.lock | 10 +++++-----
3 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/package.json b/package.json
index 34a022f2d8d6..ffc2a66ea0a9 100644
--- a/package.json
+++ b/package.json
@@ -272,7 +272,7 @@
},
"dependencies": {
"@babel/runtime": "patch:@babel/runtime@npm%3A7.24.0#~/.yarn/patches/@babel-runtime-npm-7.24.0-7eb1dd11a2.patch",
- "@blockaid/ppom_release": "^1.5.2",
+ "@blockaid/ppom_release": "^1.5.3",
"@ensdomains/content-hash": "^2.5.7",
"@ethereumjs/tx": "^4.1.1",
"@ethersproject/abi": "^5.6.4",
diff --git a/ui/pages/confirmations/components/security-provider-banner-alert/blockaid-banner-alert/__snapshots__/blockaid-banner-alert.test.js.snap b/ui/pages/confirmations/components/security-provider-banner-alert/blockaid-banner-alert/__snapshots__/blockaid-banner-alert.test.js.snap
index 127e733ad95d..af7e4e9e05dd 100644
--- a/ui/pages/confirmations/components/security-provider-banner-alert/blockaid-banner-alert/__snapshots__/blockaid-banner-alert.test.js.snap
+++ b/ui/pages/confirmations/components/security-provider-banner-alert/blockaid-banner-alert/__snapshots__/blockaid-banner-alert.test.js.snap
@@ -54,7 +54,7 @@ exports[`Blockaid Banner Alert should render 'danger' UI when securityAlertRespo
Something doesn't look right?
@@ -151,7 +151,7 @@ exports[`Blockaid Banner Alert should render 'warning' UI when securityAlertResp
Something doesn't look right?
@@ -248,7 +248,7 @@ exports[`Blockaid Banner Alert should render 'warning' UI when securityAlertResp
Something doesn't look right?
@@ -346,7 +346,7 @@ exports[`Blockaid Banner Alert should render details section even when features
Something doesn't look right?
@@ -457,7 +457,7 @@ exports[`Blockaid Banner Alert should render details when provided 1`] = `
Something doesn't look right?
@@ -556,7 +556,7 @@ exports[`Blockaid Banner Alert should render link to report url 1`] = `
Something doesn't look right?
diff --git a/yarn.lock b/yarn.lock
index ea8a91ae8270..b9d85e38829f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1704,10 +1704,10 @@ __metadata:
languageName: node
linkType: hard
-"@blockaid/ppom_release@npm:^1.5.2":
- version: 1.5.2
- resolution: "@blockaid/ppom_release@npm:1.5.2"
- checksum: 10/b47af74e8a315d996abb8371a7b28f9923bf78272cc408b2307024e2050b57f36c53b6b9a57b276b0910b449ebb384897e293abad356131ccf65c6c3c5ca31ae
+"@blockaid/ppom_release@npm:^1.5.3":
+ version: 1.5.3
+ resolution: "@blockaid/ppom_release@npm:1.5.3"
+ checksum: 10/3e8a16866b477eef247c4a65c80d361e7429389e7e760c0497bc69269526e2325fa15cdbf93455c1655877a7760c6b4fc9ce87d80f0290483160632300bcfbc8
languageName: node
linkType: hard
@@ -25936,7 +25936,7 @@ __metadata:
"@babel/preset-typescript": "npm:^7.23.2"
"@babel/register": "npm:^7.22.15"
"@babel/runtime": "patch:@babel/runtime@npm%3A7.24.0#~/.yarn/patches/@babel-runtime-npm-7.24.0-7eb1dd11a2.patch"
- "@blockaid/ppom_release": "npm:^1.5.2"
+ "@blockaid/ppom_release": "npm:^1.5.3"
"@ensdomains/content-hash": "npm:^2.5.7"
"@ethereumjs/tx": "npm:^4.1.1"
"@ethersproject/abi": "npm:^5.6.4"
From a7d5a56d1fd2273048ccdab4ebfa6619f9faf314 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Tavares?=
Date: Tue, 17 Sep 2024 11:00:38 +0100
Subject: [PATCH 03/37] fix: permit UI integration tests (#26365)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
Improves permit UI integration tests, by ensuring that the simulation
details component is rendered properly.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/26365?quickstart=1)
## **Related issues**
Fixes:
## **Manual testing steps**
1. Go to this page...
2.
3.
## **Screenshots/Recordings**
### **Before**
### **After**
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
---
...ironment-jsdom-npm-29.7.0-0b72dd0e0b.patch | 16 +++
package.json | 2 +-
.../confirmations/signatures/permit.test.tsx | 133 +++++++++++++-----
.../data/integration-init-state.json | 19 ++-
yarn.lock | 25 +++-
5 files changed, 153 insertions(+), 42 deletions(-)
create mode 100644 .yarn/patches/jest-environment-jsdom-npm-29.7.0-0b72dd0e0b.patch
diff --git a/.yarn/patches/jest-environment-jsdom-npm-29.7.0-0b72dd0e0b.patch b/.yarn/patches/jest-environment-jsdom-npm-29.7.0-0b72dd0e0b.patch
new file mode 100644
index 000000000000..94e712adf366
--- /dev/null
+++ b/.yarn/patches/jest-environment-jsdom-npm-29.7.0-0b72dd0e0b.patch
@@ -0,0 +1,16 @@
+diff --git a/build/index.js b/build/index.js
+index 2e6c16c33c2f588cf8d6a5717ac776bb8908bd0d..5534a739c6bc7cda9e0f8439656a6215dfacc26a 100644
+--- a/build/index.js
++++ b/build/index.js
+@@ -95,6 +95,11 @@ class JSDOMEnvironment {
+
+ // TODO: remove this ASAP, but it currently causes tests to run really slow
+ global.Buffer = Buffer;
++ // Needed to support toChecksumAddress from the ethereumjs-util@7.1.5.
++ // It converts a hex string to a buffer and then expects it to be an instanceof Uint8Array.
++ // And although on Node env that buffer is an instance of Uint8Array, on JSDOM it is not.
++ // So we need to override the jsdom Uint8Array with Node Uint8Array.
++ global.Uint8Array = Uint8Array;
+
+ // Report uncaught errors.
+ this.errorEventListener = event => {
diff --git a/package.json b/package.json
index ffc2a66ea0a9..d850945c4d63 100644
--- a/package.json
+++ b/package.json
@@ -609,7 +609,7 @@
"ini": "^3.0.0",
"jest": "^29.7.0",
"jest-canvas-mock": "^2.3.1",
- "jest-environment-jsdom": "^29.7.0",
+ "jest-environment-jsdom": "patch:jest-environment-jsdom@npm%3A29.7.0#~/.yarn/patches/jest-environment-jsdom-npm-29.7.0-0b72dd0e0b.patch",
"jsdom": "^16.7.0",
"json-schema-to-ts": "^3.0.1",
"koa": "^2.7.0",
diff --git a/test/integration/confirmations/signatures/permit.test.tsx b/test/integration/confirmations/signatures/permit.test.tsx
index f0a58da87b97..3670b654502d 100644
--- a/test/integration/confirmations/signatures/permit.test.tsx
+++ b/test/integration/confirmations/signatures/permit.test.tsx
@@ -1,4 +1,5 @@
-import { fireEvent, waitFor } from '@testing-library/react';
+import { act, fireEvent, waitFor, screen } from '@testing-library/react';
+import nock from 'nock';
import { ApprovalType } from '@metamask/controller-utils';
import mockMetaMaskState from '../../data/integration-init-state.json';
import { integrationTestRender } from '../../../lib/render-helpers';
@@ -72,11 +73,15 @@ describe('Permit Confirmation', () => {
jest.resetAllMocks();
mockedBackgroundConnection.submitRequestToBackground.mockImplementation(
createMockImplementation({
- getTokenStandardAndDetails: { decimal: '10' },
+ getTokenStandardAndDetails: { decimals: '2' },
}),
);
});
+ afterEach(() => {
+ nock.cleanAll();
+ });
+
it('displays the header account modal with correct data', async () => {
const account =
mockMetaMaskState.internalAccounts.accounts[
@@ -89,32 +94,32 @@ describe('Permit Confirmation', () => {
account.address,
);
- const { getByTestId, queryByTestId } = await integrationTestRender({
- preloadedState: mockedMetaMaskState,
- backgroundConnection: backgroundConnectionMocked,
+ await act(async () => {
+ await integrationTestRender({
+ preloadedState: mockedMetaMaskState,
+ backgroundConnection: backgroundConnectionMocked,
+ });
});
- expect(getByTestId('header-account-name')).toHaveTextContent(accountName);
- expect(getByTestId('header-network-display-name')).toHaveTextContent(
+ expect(screen.getByTestId('header-account-name')).toHaveTextContent(
+ accountName,
+ );
+ expect(screen.getByTestId('header-network-display-name')).toHaveTextContent(
'Chain 5',
);
- fireEvent.click(getByTestId('header-info__account-details-button'));
-
- await waitFor(() => {
- expect(
- getByTestId('confirmation-account-details-modal__account-name'),
- ).toBeInTheDocument();
- });
+ fireEvent.click(screen.getByTestId('header-info__account-details-button'));
expect(
- getByTestId('confirmation-account-details-modal__account-name'),
+ await screen.findByTestId(
+ 'confirmation-account-details-modal__account-name',
+ ),
).toHaveTextContent(accountName);
- expect(getByTestId('address-copy-button-text')).toHaveTextContent(
+ expect(screen.getByTestId('address-copy-button-text')).toHaveTextContent(
'0x0DCD5...3E7bc',
);
expect(
- getByTestId('confirmation-account-details-modal__account-balance'),
+ screen.getByTestId('confirmation-account-details-modal__account-balance'),
).toHaveTextContent('1.58271596ETH');
let confirmAccountDetailsModalMetricsEvent;
@@ -147,12 +152,14 @@ describe('Permit Confirmation', () => {
);
fireEvent.click(
- getByTestId('confirmation-account-details-modal__close-button'),
+ screen.getByTestId('confirmation-account-details-modal__close-button'),
);
await waitFor(() => {
expect(
- queryByTestId('confirmation-account-details-modal__account-name'),
+ screen.queryByTestId(
+ 'confirmation-account-details-modal__account-name',
+ ),
).not.toBeInTheDocument();
});
});
@@ -168,18 +175,52 @@ describe('Permit Confirmation', () => {
account.address,
);
- const { getByText } = await integrationTestRender({
- preloadedState: mockedMetaMaskState,
- backgroundConnection: backgroundConnectionMocked,
+ await act(async () => {
+ await integrationTestRender({
+ preloadedState: mockedMetaMaskState,
+ backgroundConnection: backgroundConnectionMocked,
+ });
});
- expect(getByText('Spending cap request')).toBeInTheDocument();
+ expect(screen.getByText('Spending cap request')).toBeInTheDocument();
expect(
- getByText('This site wants permission to spend your tokens.'),
+ screen.getByText('This site wants permission to spend your tokens.'),
).toBeInTheDocument();
});
it('displays the simulation section', async () => {
+ const scope = nock('https://price.api.cx.metamask.io')
+ .persist()
+ .get('/v2/chains/1/spot-prices')
+ .query({
+ tokenAddresses:
+ '0x0000000000000000000000000000000000000000,0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
+ vsCurrency: 'ETH',
+ includeMarketData: 'true',
+ })
+ .reply(200, {
+ '0xcccccccccccccccccccccccccccccccccccccccc': {
+ allTimeHigh: 12,
+ allTimeLow: 1,
+ circulatingSupply: 50000,
+ dilutedMarketCap: 50000,
+ high1d: 11,
+ low1d: 9.9,
+ marketCap: 10000,
+ marketCapPercentChange1d: 1,
+ price: 10,
+ priceChange1d: 0.5,
+ pricePercentChange1d: 1,
+ pricePercentChange1h: 0,
+ pricePercentChange1y: 80,
+ pricePercentChange7d: 2,
+ pricePercentChange14d: 5,
+ pricePercentChange30d: 10,
+ pricePercentChange200d: 50,
+ totalVolume: 100,
+ },
+ });
+
const account =
mockMetaMaskState.internalAccounts.accounts[
mockMetaMaskState.internalAccounts
@@ -190,12 +231,26 @@ describe('Permit Confirmation', () => {
account.address,
);
- const { getByTestId } = await integrationTestRender({
- preloadedState: mockedMetaMaskState,
- backgroundConnection: backgroundConnectionMocked,
+ await act(async () => {
+ await integrationTestRender({
+ preloadedState: {
+ ...mockedMetaMaskState,
+ selectedNetworkClientId: 'testNetworkConfigurationId',
+ providerConfig: {
+ type: 'rpc',
+ nickname: 'test mainnet',
+ chainId: '0x1',
+ ticker: 'ETH',
+ id: 'chain1',
+ },
+ },
+ backgroundConnection: backgroundConnectionMocked,
+ });
});
- const simulationSection = getByTestId('confirmation__simulation_section');
+ const simulationSection = screen.getByTestId(
+ 'confirmation__simulation_section',
+ );
expect(simulationSection).toBeInTheDocument();
expect(simulationSection).toHaveTextContent('Estimated changes');
expect(simulationSection).toHaveTextContent(
@@ -203,7 +258,17 @@ describe('Permit Confirmation', () => {
);
expect(simulationSection).toHaveTextContent('Spending cap');
expect(simulationSection).toHaveTextContent('0xCcCCc...ccccC');
- expect(getByTestId('simulation-token-value')).toHaveTextContent('3,000');
+ expect(screen.getByTestId('simulation-token-value')).toHaveTextContent(
+ '30',
+ );
+
+ const individualFiatDisplay = await screen.findByTestId(
+ 'individual-fiat-display',
+ );
+ expect(individualFiatDisplay).toHaveTextContent('$166,836.00');
+
+ scope.done();
+ expect(scope.isDone()).toBe(true);
});
it('displays the MMI header warning when account signing is not the same as the account selected', async () => {
@@ -221,9 +286,11 @@ describe('Permit Confirmation', () => {
account.address,
);
- const { getByText } = await integrationTestRender({
- preloadedState: mockedMetaMaskState,
- backgroundConnection: backgroundConnectionMocked,
+ await act(async () => {
+ await integrationTestRender({
+ preloadedState: mockedMetaMaskState,
+ backgroundConnection: backgroundConnectionMocked,
+ });
});
const mismatchAccountText = `Your selected account (${shortenAddress(
@@ -232,6 +299,6 @@ describe('Permit Confirmation', () => {
account.address,
)})`;
- expect(getByText(mismatchAccountText)).toBeInTheDocument();
+ expect(screen.getByText(mismatchAccountText)).toBeInTheDocument();
});
});
diff --git a/test/integration/data/integration-init-state.json b/test/integration/data/integration-init-state.json
index 0e935a7a9a8e..27cd1dcfd83a 100644
--- a/test/integration/data/integration-init-state.json
+++ b/test/integration/data/integration-init-state.json
@@ -656,18 +656,19 @@
},
"networkConfigurations": {
"testNetworkConfigurationId": {
- "rpcUrl": "https://testrpc.com",
"chainId": "0x1",
+ "id": "testNetworkConfigurationId",
"nickname": "Custom Mainnet RPC",
- "type": "rpc",
- "id": "testNetworkConfigurationId"
+ "rpcUrl": "https://testrpc.com",
+ "ticker": "ETH",
+ "type": "rpc"
},
"goerli-network-id": {
- "type": "rpc",
"chainId": "0x5",
- "ticker": "ETH",
+ "id": "goerli-network-id",
"nickname": "Chain 5",
- "id": "goerli-network-id"
+ "ticker": "ETH",
+ "type": "rpc"
}
},
"networksMetadata": {
@@ -682,6 +683,12 @@
"1559": true
},
"status": "available"
+ },
+ "testNetworkConfigurationId": {
+ "EIPS": {
+ "1559": true
+ },
+ "status": "available"
}
},
"nftsDropdownState": {
diff --git a/yarn.lock b/yarn.lock
index b9d85e38829f..1c0a3d9ab60e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -23313,7 +23313,7 @@ __metadata:
languageName: node
linkType: hard
-"jest-environment-jsdom@npm:^29.7.0":
+"jest-environment-jsdom@npm:29.7.0":
version: 29.7.0
resolution: "jest-environment-jsdom@npm:29.7.0"
dependencies:
@@ -23334,6 +23334,27 @@ __metadata:
languageName: node
linkType: hard
+"jest-environment-jsdom@patch:jest-environment-jsdom@npm%3A29.7.0#~/.yarn/patches/jest-environment-jsdom-npm-29.7.0-0b72dd0e0b.patch":
+ version: 29.7.0
+ resolution: "jest-environment-jsdom@patch:jest-environment-jsdom@npm%3A29.7.0#~/.yarn/patches/jest-environment-jsdom-npm-29.7.0-0b72dd0e0b.patch::version=29.7.0&hash=a6aa71"
+ dependencies:
+ "@jest/environment": "npm:^29.7.0"
+ "@jest/fake-timers": "npm:^29.7.0"
+ "@jest/types": "npm:^29.6.3"
+ "@types/jsdom": "npm:^20.0.0"
+ "@types/node": "npm:*"
+ jest-mock: "npm:^29.7.0"
+ jest-util: "npm:^29.7.0"
+ jsdom: "npm:^20.0.0"
+ peerDependencies:
+ canvas: ^2.5.0
+ peerDependenciesMeta:
+ canvas:
+ optional: true
+ checksum: 10/ccc6dc855d841cbcaac17c3f8b25bd63827c7766bf4ee555ee7b7c2b9707ae172659be4a813fdddbdd2a933d9d6c23a97e13924e176a68cf44299c57bf1e3009
+ languageName: node
+ linkType: hard
+
"jest-environment-node@npm:^29.6.4, jest-environment-node@npm:^29.7.0":
version: 29.7.0
resolution: "jest-environment-node@npm:29.7.0"
@@ -26216,7 +26237,7 @@ __metadata:
is-retry-allowed: "npm:^2.2.0"
jest: "npm:^29.7.0"
jest-canvas-mock: "npm:^2.3.1"
- jest-environment-jsdom: "npm:^29.7.0"
+ jest-environment-jsdom: "patch:jest-environment-jsdom@npm%3A29.7.0#~/.yarn/patches/jest-environment-jsdom-npm-29.7.0-0b72dd0e0b.patch"
jest-junit: "npm:^14.0.1"
jsdom: "npm:^16.7.0"
json-rpc-engine: "npm:^6.1.0"
From 39c75a8f34ce8020257a9dcf2a2c86273f3a7f4c Mon Sep 17 00:00:00 2001
From: Matthew Walsh
Date: Tue, 17 Sep 2024 11:56:13 +0100
Subject: [PATCH 04/37] fix: incomplete transactions on startup (#26963)
Upgrade the `TransactionController` to `37.0.0`.
Prevent various scenarios triggering the `signed or submitted` alert .
Remove unapproved transaction fixtures as no longer supported.
---
.storybook/main.js | 4 +
app/scripts/background.js | 2 -
app/scripts/lib/ppom/ppom-middleware.test.ts | 1 +
app/scripts/lib/transaction/mmi-hooks.test.ts | 19 -
app/scripts/lib/transaction/mmi-hooks.ts | 12 -
app/scripts/metamask-controller.js | 10 +-
lavamoat/browserify/beta/policy.json | 10 +-
lavamoat/browserify/flask/policy.json | 10 +-
lavamoat/browserify/main/policy.json | 10 +-
lavamoat/browserify/mmi/policy.json | 10 +-
package.json | 2 +-
test/e2e/fixture-builder.js | 599 +-----------------
test/e2e/page-objects/flows/transaction.ts | 40 ++
.../pages/confirmations/legacy/navigation.ts | 57 ++
test/e2e/page-objects/pages/test-dapp.ts | 37 ++
.../contract-interaction-redesign.spec.ts | 44 +-
.../tests/transaction/edit-gas-fee.spec.js | 32 +-
.../transaction/navigate-transactions.spec.js | 234 +++----
test/e2e/tests/transaction/send-edit.spec.js | 48 +-
ui/__mocks__/ethereumjs-util.js | 6 +
yarn.lock | 36 +-
21 files changed, 349 insertions(+), 874 deletions(-)
create mode 100644 test/e2e/page-objects/flows/transaction.ts
create mode 100644 test/e2e/page-objects/pages/confirmations/legacy/navigation.ts
create mode 100644 test/e2e/page-objects/pages/test-dapp.ts
create mode 100644 ui/__mocks__/ethereumjs-util.js
diff --git a/.storybook/main.js b/.storybook/main.js
index 554f6d955ee0..d63d924aa2e2 100644
--- a/.storybook/main.js
+++ b/.storybook/main.js
@@ -48,6 +48,10 @@ module.exports = {
config.resolve.alias['../../../../../../store/actions'] = require.resolve(
'../ui/__mocks__/actions.js',
);
+ // Import within controller-utils crashes storybook.
+ config.resolve.alias['@ethereumjs/util'] = require.resolve(
+ '../ui/__mocks__/ethereumjs-util.js',
+ );
config.resolve.fallback = {
child_process: false,
constants: false,
diff --git a/app/scripts/background.js b/app/scripts/background.js
index 3c50f8760b71..2a29de9af601 100644
--- a/app/scripts/background.js
+++ b/app/scripts/background.js
@@ -1005,8 +1005,6 @@ export function setupController(
updateBadge,
);
- controller.txController.initApprovals();
-
/**
* Formats a count for display as a badge label.
*
diff --git a/app/scripts/lib/ppom/ppom-middleware.test.ts b/app/scripts/lib/ppom/ppom-middleware.test.ts
index 6b9c78a7ddc7..cbd3674f65c8 100644
--- a/app/scripts/lib/ppom/ppom-middleware.test.ts
+++ b/app/scripts/lib/ppom/ppom-middleware.test.ts
@@ -19,6 +19,7 @@ import {
import { SecurityAlertResponse } from './types';
jest.mock('./ppom-util');
+jest.mock('@metamask/controller-utils');
const SECURITY_ALERT_ID_MOCK = '123';
const INTERNAL_ACCOUNT_ADDRESS = '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b';
diff --git a/app/scripts/lib/transaction/mmi-hooks.test.ts b/app/scripts/lib/transaction/mmi-hooks.test.ts
index fee5dff83de5..45d0b83c2341 100644
--- a/app/scripts/lib/transaction/mmi-hooks.test.ts
+++ b/app/scripts/lib/transaction/mmi-hooks.test.ts
@@ -2,7 +2,6 @@ import { TransactionStatus } from '@metamask/transaction-controller';
import {
afterTransactionSign,
beforeCheckPendingTransaction,
- beforeTransactionApproveOnInit,
beforeTransactionPublish,
getAdditionalSignArguments,
} from './mmi-hooks';
@@ -85,24 +84,6 @@ describe('MMI hooks', () => {
});
});
- describe('beforeTransactionApproveOnInit', () => {
- it('returns true if txMeta has custodyStatus', () => {
- // TODO: Replace `any` with type
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const txMeta = { custodyStatus: TransactionStatus.approved } as any;
- const result = beforeTransactionApproveOnInit(txMeta);
- expect(result).toBe(false);
- });
-
- it('returns false if txMeta has no custodyStatus', () => {
- // TODO: Replace `any` with type
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const txMeta = { to: toMocked } as any;
- const result = beforeTransactionApproveOnInit(txMeta);
- expect(result).toBe(true);
- });
- });
-
describe('beforeCheckPendingTransaction', () => {
it('returns true if txMeta has custodyStatus', () => {
const txMeta = {
diff --git a/app/scripts/lib/transaction/mmi-hooks.ts b/app/scripts/lib/transaction/mmi-hooks.ts
index d4dc3cc4dcda..1716fe738c04 100644
--- a/app/scripts/lib/transaction/mmi-hooks.ts
+++ b/app/scripts/lib/transaction/mmi-hooks.ts
@@ -53,18 +53,6 @@ export function getAdditionalSignArguments(
return [txMeta.custodyStatus ? txMeta : undefined];
}
-/**
- * Whether or not should run the logic before approve the transaction when transaction controller is rebooted.
- *
- * @param txMeta - The transaction meta.
- */
-
-export function beforeTransactionApproveOnInit(
- txMeta: TransactionMeta,
-): boolean {
- return !txMeta?.custodyStatus;
-}
-
/**
* Whether or not should run the logic before checking the transaction when checking pending transactions.
*
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index 0b9f0d20bf63..0cceb966d5db 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -246,7 +246,6 @@ import {
afterTransactionSign as afterTransactionSignMMI,
beforeCheckPendingTransaction as beforeCheckPendingTransactionMMI,
beforeTransactionPublish as beforeTransactionPublishMMI,
- beforeTransactionApproveOnInit as beforeApproveOnInitMMI,
getAdditionalSignArguments as getAdditionalSignArgumentsMMI,
} from './lib/transaction/mmi-hooks';
///: END:ONLY_INCLUDE_IF
@@ -1847,7 +1846,6 @@ export default class MetamaskController extends EventEmitter {
),
beforeCheckPendingTransaction:
beforeCheckPendingTransactionMMI.bind(this),
- beforeApproveOnInit: beforeApproveOnInitMMI.bind(this),
beforePublish: beforeTransactionPublishMMI.bind(this),
getAdditionalSignArguments: getAdditionalSignArgumentsMMI.bind(this),
///: END:ONLY_INCLUDE_IF
@@ -4889,11 +4887,11 @@ export default class MetamaskController extends EventEmitter {
* by creating a new transaction.
*
* @param {number} originalTxId - the id of the txMeta that you want to
- * attempt to cancel
+ * attempt to cancel
* @param {import(
* './controllers/transactions'
* ).CustomGasSettings} [customGasSettings] - overrides to use for gas params
- * instead of allowing this method to generate them
+ * instead of allowing this method to generate them
* @param options
* @returns {object} MetaMask state
*/
@@ -4912,11 +4910,11 @@ export default class MetamaskController extends EventEmitter {
* by creating a new transaction.
*
* @param {number} originalTxId - the id of the txMeta that you want to
- * attempt to speed up
+ * attempt to speed up
* @param {import(
* './controllers/transactions'
* ).CustomGasSettings} [customGasSettings] - overrides to use for gas params
- * instead of allowing this method to generate them
+ * instead of allowing this method to generate them
* @param options
* @returns {object} MetaMask state
*/
diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json
index b27b95f111a4..43f83e019cee 100644
--- a/lavamoat/browserify/beta/policy.json
+++ b/lavamoat/browserify/beta/policy.json
@@ -3082,6 +3082,7 @@
"@ethersproject/abi": true,
"@ethersproject/contracts": true,
"@ethersproject/providers": true,
+ "@metamask/base-controller": true,
"@metamask/controller-utils": true,
"@metamask/eth-query": true,
"@metamask/gas-fee-controller": true,
@@ -3089,7 +3090,6 @@
"@metamask/name-controller>async-mutex": true,
"@metamask/network-controller": true,
"@metamask/rpc-errors": true,
- "@metamask/transaction-controller>@metamask/base-controller": true,
"@metamask/transaction-controller>@metamask/nonce-tracker": true,
"@metamask/utils": true,
"bn.js": true,
@@ -3101,14 +3101,6 @@
"webpack>events": true
}
},
- "@metamask/transaction-controller>@metamask/base-controller": {
- "globals": {
- "setTimeout": true
- },
- "packages": {
- "immer": true
- }
- },
"@metamask/transaction-controller>@metamask/nonce-tracker": {
"packages": {
"@ethersproject/providers": true,
diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json
index b27b95f111a4..43f83e019cee 100644
--- a/lavamoat/browserify/flask/policy.json
+++ b/lavamoat/browserify/flask/policy.json
@@ -3082,6 +3082,7 @@
"@ethersproject/abi": true,
"@ethersproject/contracts": true,
"@ethersproject/providers": true,
+ "@metamask/base-controller": true,
"@metamask/controller-utils": true,
"@metamask/eth-query": true,
"@metamask/gas-fee-controller": true,
@@ -3089,7 +3090,6 @@
"@metamask/name-controller>async-mutex": true,
"@metamask/network-controller": true,
"@metamask/rpc-errors": true,
- "@metamask/transaction-controller>@metamask/base-controller": true,
"@metamask/transaction-controller>@metamask/nonce-tracker": true,
"@metamask/utils": true,
"bn.js": true,
@@ -3101,14 +3101,6 @@
"webpack>events": true
}
},
- "@metamask/transaction-controller>@metamask/base-controller": {
- "globals": {
- "setTimeout": true
- },
- "packages": {
- "immer": true
- }
- },
"@metamask/transaction-controller>@metamask/nonce-tracker": {
"packages": {
"@ethersproject/providers": true,
diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json
index b27b95f111a4..43f83e019cee 100644
--- a/lavamoat/browserify/main/policy.json
+++ b/lavamoat/browserify/main/policy.json
@@ -3082,6 +3082,7 @@
"@ethersproject/abi": true,
"@ethersproject/contracts": true,
"@ethersproject/providers": true,
+ "@metamask/base-controller": true,
"@metamask/controller-utils": true,
"@metamask/eth-query": true,
"@metamask/gas-fee-controller": true,
@@ -3089,7 +3090,6 @@
"@metamask/name-controller>async-mutex": true,
"@metamask/network-controller": true,
"@metamask/rpc-errors": true,
- "@metamask/transaction-controller>@metamask/base-controller": true,
"@metamask/transaction-controller>@metamask/nonce-tracker": true,
"@metamask/utils": true,
"bn.js": true,
@@ -3101,14 +3101,6 @@
"webpack>events": true
}
},
- "@metamask/transaction-controller>@metamask/base-controller": {
- "globals": {
- "setTimeout": true
- },
- "packages": {
- "immer": true
- }
- },
"@metamask/transaction-controller>@metamask/nonce-tracker": {
"packages": {
"@ethersproject/providers": true,
diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json
index 56b9dc57a34a..7641b2869288 100644
--- a/lavamoat/browserify/mmi/policy.json
+++ b/lavamoat/browserify/mmi/policy.json
@@ -3174,6 +3174,7 @@
"@ethersproject/abi": true,
"@ethersproject/contracts": true,
"@ethersproject/providers": true,
+ "@metamask/base-controller": true,
"@metamask/controller-utils": true,
"@metamask/eth-query": true,
"@metamask/gas-fee-controller": true,
@@ -3181,7 +3182,6 @@
"@metamask/name-controller>async-mutex": true,
"@metamask/network-controller": true,
"@metamask/rpc-errors": true,
- "@metamask/transaction-controller>@metamask/base-controller": true,
"@metamask/transaction-controller>@metamask/nonce-tracker": true,
"@metamask/utils": true,
"bn.js": true,
@@ -3193,14 +3193,6 @@
"webpack>events": true
}
},
- "@metamask/transaction-controller>@metamask/base-controller": {
- "globals": {
- "setTimeout": true
- },
- "packages": {
- "immer": true
- }
- },
"@metamask/transaction-controller>@metamask/nonce-tracker": {
"packages": {
"@ethersproject/providers": true,
diff --git a/package.json b/package.json
index d850945c4d63..b3b5b22f7e86 100644
--- a/package.json
+++ b/package.json
@@ -359,7 +359,7 @@
"@metamask/snaps-rpc-methods": "^11.0.0",
"@metamask/snaps-sdk": "^6.3.0",
"@metamask/snaps-utils": "^8.0.1",
- "@metamask/transaction-controller": "^35.2.0",
+ "@metamask/transaction-controller": "^37.0.0",
"@metamask/user-operation-controller": "^13.0.0",
"@metamask/utils": "^9.1.0",
"@ngraveio/bc-ur": "^1.1.12",
diff --git a/test/e2e/fixture-builder.js b/test/e2e/fixture-builder.js
index 357cd95600f4..1a4014bcc30a 100644
--- a/test/e2e/fixture-builder.js
+++ b/test/e2e/fixture-builder.js
@@ -8,7 +8,7 @@ const { mockNetworkState } = require('../stub/networks');
const { CHAIN_IDS } = require('../../shared/constants/network');
const { SMART_CONTRACTS } = require('./seeder/smart-contracts');
-const { DAPP_URL, DAPP_ONE_URL, ACCOUNT_1 } = require('./helpers');
+const { DAPP_URL, DAPP_ONE_URL } = require('./helpers');
const { DEFAULT_FIXTURE_ACCOUNT, ERC_4337_ACCOUNT } = require('./constants');
const {
defaultFixture,
@@ -234,6 +234,22 @@ class FixtureBuilder {
return this.withNetworkController({ selectedNetworkClientId: 'mainnet' });
}
+ withNetworkControllerOnOptimism() {
+ return this.withNetworkController({
+ networkConfigurations: {
+ networkConfigurationId: {
+ chainId: CHAIN_IDS.OPTIMISM,
+ nickname: 'Localhost 8545',
+ rpcPrefs: {},
+ rpcUrl: 'https://mainnet.infura.io',
+ ticker: 'ETH',
+ networkConfigurationId: 'networkConfigurationId',
+ id: 'networkConfigurationId',
+ },
+ },
+ });
+ }
+
withNetworkControllerDoubleGanache() {
const ganacheNetworks = mockNetworkState(
{
@@ -811,587 +827,6 @@ class FixtureBuilder {
return this;
}
- withTransactionControllerMultipleTransactions() {
- return this.withTransactionController({
- transactions: {
- '7087d1d7-f0e8-4c0f-a903-6d9daa392baf': {
- chainId: CHAIN_IDS.LOCALHOST,
- dappSuggestedGasFees: {
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- },
- history: [
- {
- chainId: CHAIN_IDS.LOCALHOST,
- dappSuggestedGasFees: {
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- },
- id: '7087d1d7-f0e8-4c0f-a903-6d9daa392baf',
- loadingDefaults: true,
- origin: 'https://metamask.github.io',
- status: 'unapproved',
- time: 1631545991949,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
- value: '0x29a2241af62c0000',
- },
- type: 'simpleSend',
- },
- [
- {
- note: 'Added new unapproved transaction.',
- op: 'replace',
- path: '/loadingDefaults',
- timestamp: 1631545992244,
- value: false,
- },
- {
- op: 'add',
- path: '/simulationData',
- value: {
- error: {
- code: 'disabled',
- message: 'Simulation disabled',
- },
- tokenBalanceChanges: [],
- },
- note: 'TransactionController#updateSimulationData - Update simulation data',
- timestamp: 1631545992244,
- },
- ],
- ],
- simulationData: {
- error: {
- code: 'disabled',
- message: 'Simulation disabled',
- },
- tokenBalanceChanges: [],
- },
- id: '7087d1d7-f0e8-4c0f-a903-6d9daa392baf',
- loadingDefaults: false,
- origin: 'https://metamask.github.io',
- status: 'unapproved',
- time: 1631545991949,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
- value: '0x29a2241af62c0000',
- },
- type: 'simpleSend',
- },
- '6eab4240-3762-4581-abc5-cd91eab6964e': {
- chainId: CHAIN_IDS.LOCALHOST,
- dappSuggestedGasFees: {
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- },
- history: [
- {
- chainId: CHAIN_IDS.LOCALHOST,
- dappSuggestedGasFees: {
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- },
- id: '6eab4240-3762-4581-abc5-cd91eab6964e',
- loadingDefaults: true,
- origin: 'https://metamask.github.io',
- status: 'unapproved',
- time: 1631545994578,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
- value: '0x29a2241af62c0000',
- },
- type: 'simpleSend',
- },
- [
- {
- note: 'Added new unapproved transaction.',
- op: 'replace',
- path: '/loadingDefaults',
- timestamp: 1631545994695,
- value: false,
- },
- {
- op: 'add',
- path: '/simulationData',
- value: {
- error: {
- code: 'disabled',
- message: 'Simulation disabled',
- },
- tokenBalanceChanges: [],
- },
- note: 'TransactionController#updateSimulationData - Update simulation data',
- timestamp: 1631545992244,
- },
- ],
- ],
- simulationData: {
- error: {
- code: 'disabled',
- message: 'Simulation disabled',
- },
- tokenBalanceChanges: [],
- },
- id: '6eab4240-3762-4581-abc5-cd91eab6964e',
- loadingDefaults: false,
- origin: 'https://metamask.github.io',
- status: 'unapproved',
- time: 1631545994578,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
- value: '0x29a2241af62c0000',
- },
- type: 'simpleSend',
- },
- 'c15eee26-11d6-4914-a70e-36ef9a3bcacb': {
- chainId: CHAIN_IDS.LOCALHOST,
- dappSuggestedGasFees: {
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- },
- history: [
- {
- chainId: CHAIN_IDS.LOCALHOST,
- dappSuggestedGasFees: {
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- },
- id: 'c15eee26-11d6-4914-a70e-36ef9a3bcacb',
- loadingDefaults: true,
- origin: 'https://metamask.github.io',
- status: 'unapproved',
- time: 1631545996673,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
- value: '0x29a2241af62c0000',
- },
- type: 'simpleSend',
- },
- [
- {
- note: 'Added new unapproved transaction.',
- op: 'replace',
- path: '/loadingDefaults',
- timestamp: 1631545996678,
- value: false,
- },
- {
- op: 'add',
- path: '/simulationData',
- value: {
- error: {
- code: 'disabled',
- message: 'Simulation disabled',
- },
- tokenBalanceChanges: [],
- },
- note: 'TransactionController#updateSimulationData - Update simulation data',
- timestamp: 1631545992244,
- },
- ],
- ],
- simulationData: {
- error: {
- code: 'disabled',
- message: 'Simulation disabled',
- },
- tokenBalanceChanges: [],
- },
- id: 'c15eee26-11d6-4914-a70e-36ef9a3bcacb',
- loadingDefaults: false,
- origin: 'https://metamask.github.io',
- status: 'unapproved',
- time: 1631545996673,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
- value: '0x29a2241af62c0000',
- },
- type: 'simpleSend',
- },
- 'dfa9e5ad-d069-46b1-976e-a23734971d87': {
- chainId: CHAIN_IDS.LOCALHOST,
- dappSuggestedGasFees: {
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- },
- history: [
- {
- chainId: CHAIN_IDS.LOCALHOST,
- dappSuggestedGasFees: {
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- },
- id: 'dfa9e5ad-d069-46b1-976e-a23734971d87',
- loadingDefaults: true,
- origin: 'https://metamask.github.io',
- status: 'unapproved',
- time: 1631545998675,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
- value: '0x29a2241af62c0000',
- },
- type: 'simpleSend',
- },
- [
- {
- note: 'Added new unapproved transaction.',
- op: 'replace',
- path: '/loadingDefaults',
- timestamp: 1631545998677,
- value: false,
- },
- {
- op: 'add',
- path: '/simulationData',
- value: {
- error: {
- code: 'disabled',
- message: 'Simulation disabled',
- },
- tokenBalanceChanges: [],
- },
- note: 'TransactionController#updateSimulationData - Update simulation data',
- timestamp: 1631545992244,
- },
- ],
- ],
- simulationData: {
- error: {
- code: 'disabled',
- message: 'Simulation disabled',
- },
- tokenBalanceChanges: [],
- },
- id: 'dfa9e5ad-d069-46b1-976e-a23734971d87',
- loadingDefaults: false,
- origin: 'https://metamask.github.io',
- status: 'unapproved',
- time: 1631545998675,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
- value: '0x29a2241af62c0000',
- },
- type: 'simpleSend',
- },
- },
- });
- }
-
- withTransactionControllerTypeOneTransaction() {
- return this.withTransactionController({
- transactions: {
- '13a01e77-a368-4bb9-aba9-e7435580e3b9': {
- chainId: CHAIN_IDS.LOCALHOST,
- history: [
- {
- chainId: CHAIN_IDS.LOCALHOST,
- id: '13a01e77-a368-4bb9-aba9-e7435580e3b9',
- loadingDefaults: true,
- origin: 'metamask',
- status: 'unapproved',
- time: 1617228030067,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x61a8',
- gasPrice: '0x2540be400',
- to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970',
- value: '0xde0b6b3a7640000',
- },
- type: 'simpleSend',
- },
- [
- {
- note: 'Added new unapproved transaction.',
- op: 'replace',
- path: '/loadingDefaults',
- timestamp: 1617228030069,
- value: false,
- },
- ],
- ],
- id: '13a01e77-a368-4bb9-aba9-e7435580e3b9',
- loadingDefaults: false,
- origin: 'metamask',
- primaryTransaction: {
- chainId: CHAIN_IDS.LOCALHOST,
- id: '13a01e77-a368-4bb9-aba9-e7435580e3b9',
- loadingDefaults: true,
- origin: 'metamask',
- status: 'unapproved',
- time: 1617228030067,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x61a8',
- gasPrice: '0x2540be400',
- to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970',
- value: '0xde0b6b3a7640000',
- },
- type: 'sentEther',
- },
- status: 'unapproved',
- time: 1617228030067,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x61a8',
- gasPrice: '0x2540be400',
- to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970',
- value: '0xde0b6b3a7640000',
- },
- type: 'simpleSend',
- },
- },
- });
- }
-
- withTransactionControllerTypeTwoTransaction() {
- return this.withTransactionController({
- transactions: {
- '13a01e77-a368-4bb9-aba9-e7435580e3b9': {
- chainId: CHAIN_IDS.LOCALHOST,
- history: [
- {
- chainId: CHAIN_IDS.LOCALHOST,
- id: '13a01e77-a368-4bb9-aba9-e7435580e3b9',
- loadingDefaults: true,
- origin: 'metamask',
- status: 'unapproved',
- time: 1617228030067,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x61a8',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970',
- type: '0x2',
- value: '0xde0b6b3a7640000',
- },
- type: 'simpleSend',
- },
- [
- {
- note: 'Added new unapproved transaction.',
- op: 'replace',
- path: '/loadingDefaults',
- timestamp: 1617228030069,
- value: false,
- },
- ],
- ],
- id: '13a01e77-a368-4bb9-aba9-e7435580e3b9',
- loadingDefaults: false,
- origin: 'metamask',
- primaryTransaction: {
- chainId: CHAIN_IDS.LOCALHOST,
- id: '13a01e77-a368-4bb9-aba9-e7435580e3b9',
- loadingDefaults: true,
- origin: 'metamask',
- status: 'unapproved',
- time: 1617228030067,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x61a8',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970',
- type: '0x2',
- value: '0xde0b6b3a7640000',
- },
- type: 'sentEther',
- },
- status: 'unapproved',
- time: 1617228030067,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x61a8',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970',
- type: '0x2',
- value: '0xde0b6b3a7640000',
- },
- type: 'simpleSend',
- },
- },
- });
- }
-
- withTransactionControllerOPLayer2Transaction() {
- const FROM_ADDRESS = ACCOUNT_1;
- const TRANSACTION_ID = 'f0fc75d0-181d-11ef-9546-8b2366f13afd';
- const TRANSACTION_TYPE = 'contractInteraction';
- const TEST_NETWORK_CLIENT_ID = 'networkConfigurationId';
-
- return this.withTransactionController({
- transactions: {
- [TRANSACTION_ID]: {
- actionId: 3577139671,
- chainId: '0xa',
- dappSuggestedGasFees: { gas: '0x31f10' },
- defaultGasEstimates: {
- estimateType: 'dappSuggested',
- gas: '0x31f10',
- maxFeePerGas: '0x3b014b3',
- maxPriorityFeePerGas: '0x3b014b3',
- },
- gasFeeEstimates: { gasPrice: '0x3b202d0', type: 'eth_gasPrice' },
- gasFeeEstimatesLoaded: true,
- history: [
- {
- actionId: 3577139671,
- chainId: '0xa',
- dappSuggestedGasFees: { gas: '0x31f10' },
- defaultGasEstimates: {
- estimateType: 'dappSuggested',
- gas: '0x31f10',
- maxFeePerGas: '0x3b014b3',
- maxPriorityFeePerGas: '0x3b014b3',
- },
- id: TRANSACTION_ID,
- layer1GasFee: '0x175283ae57',
- networkClientId: TEST_NETWORK_CLIENT_ID,
- origin: 'https://metamask.github.io',
- securityAlertResponse: {
- reason: 'loading',
- result_type: 'validation_in_progress',
- securityAlertId: '30626504-0069-4278-9e2e-3d7fba2e6aef',
- },
- sendFlowHistory: [],
- status: 'unapproved',
- time: 1716370234797,
- txParams: {
- data: '0x608060405234801561001057600080fd5b5033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000808190555061023b806100686000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632e1a7d4d1461005c5780638da5cb5b1461009d578063d0e30db0146100f4575b600080fd5b34801561006857600080fd5b5061008760048036038101908080359060200190929190505050610112565b6040518082815260200191505060405180910390f35b3480156100a957600080fd5b506100b26101d0565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100fc6101f6565b6040518082815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561017057600080fd5b8160008082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501580156101c5573d6000803e3d6000fd5b506000549050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60003460008082825401925050819055506000549050905600a165627a7a72305820f237db3ec816a52589d82512117bc85bc08d3537683ffeff9059108caf3e5d400029',
- from: FROM_ADDRESS,
- gas: '0x31f10',
- maxFeePerGas: '0x3b014b3',
- maxPriorityFeePerGas: '0x3b014b3',
- value: '0x0',
- },
- type: TRANSACTION_TYPE,
- userEditedGasLimit: false,
- userFeeLevel: 'dappSuggested',
- verifiedOnBlockchain: false,
- },
- [
- {
- note: 'TransactionController#updateSimulationData - Update simulation data',
- op: 'add',
- path: '/simulationData',
- timestamp: 1716370235743,
- value: {
- error: { code: 'disabled', message: 'Simulation disabled' },
- tokenBalanceChanges: [],
- },
- },
- ],
- [
- {
- note: 'TransactionController:updatesecurityAlertResponse - securityAlertResponse updated',
- op: 'replace',
- path: '/securityAlertResponse/result_type',
- timestamp: 1716370236091,
- value: 'Benign',
- },
- {
- op: 'replace',
- path: '/securityAlertResponse/reason',
- value: '',
- },
- {
- op: 'add',
- path: '/securityAlertResponse/description',
- value: '',
- },
- { op: 'add', path: '/securityAlertResponse/features', value: [] },
- {
- op: 'add',
- path: '/securityAlertResponse/block',
- value: 120385722,
- },
- {
- op: 'add',
- path: '/gasFeeEstimates',
- value: { gasPrice: '0x3b014b3', type: 'eth_gasPrice' },
- },
- { op: 'add', path: '/gasFeeEstimatesLoaded', value: true },
- ],
- ],
- id: TRANSACTION_ID,
- layer1GasFee: '0x19fdabf615',
- networkClientId: TEST_NETWORK_CLIENT_ID,
- origin: 'https://metamask.github.io',
- securityAlertResponse: {
- block: 120385722,
- description: '',
- features: [],
- reason: '',
- result_type: 'Benign',
- securityAlertId: '30626504-0069-4278-9e2e-3d7fba2e6aef',
- },
- sendFlowHistory: [],
- simulationData: {
- error: { code: 'disabled', message: 'Simulation disabled' },
- tokenBalanceChanges: [],
- },
- status: 'unapproved',
- time: 1716370234797,
- txParams: {
- data: '0x608060405234801561001057600080fd5b5033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000808190555061023b806100686000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632e1a7d4d1461005c5780638da5cb5b1461009d578063d0e30db0146100f4575b600080fd5b34801561006857600080fd5b5061008760048036038101908080359060200190929190505050610112565b6040518082815260200191505060405180910390f35b3480156100a957600080fd5b506100b26101d0565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100fc6101f6565b6040518082815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561017057600080fd5b8160008082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501580156101c5573d6000803e3d6000fd5b506000549050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60003460008082825401925050819055506000549050905600a165627a7a72305820f237db3ec816a52589d82512117bc85bc08d3537683ffeff9059108caf3e5d400029',
- from: FROM_ADDRESS,
- gas: '0x31f10',
- maxFeePerGas: '0x3b014b3',
- maxPriorityFeePerGas: '0x3b014b3',
- value: '0x0',
- },
- type: TRANSACTION_TYPE,
- userEditedGasLimit: false,
- userFeeLevel: 'dappSuggested',
- verifiedOnBlockchain: false,
- },
- },
- });
- }
-
withTransactionControllerApprovedTransaction() {
return this.withTransactionController({
transactions: {
diff --git a/test/e2e/page-objects/flows/transaction.ts b/test/e2e/page-objects/flows/transaction.ts
new file mode 100644
index 000000000000..e2fdbd652034
--- /dev/null
+++ b/test/e2e/page-objects/flows/transaction.ts
@@ -0,0 +1,40 @@
+import { TransactionParams } from '@metamask/transaction-controller';
+import { DEFAULT_FIXTURE_ACCOUNT } from '../../constants';
+import { Driver } from '../../webdriver/driver';
+import HomePage from '../pages/homepage';
+import SendTokenPage from '../pages/send/send-token-page';
+import TestDapp from '../pages/test-dapp';
+
+export const createInternalTransaction = async (driver: Driver) => {
+ // Firefox has incorrect balance if send flow started too quickly.
+ await driver.delay(1000);
+
+ const homePage = new HomePage(driver);
+ await homePage.startSendFlow();
+
+ const sendToPage = new SendTokenPage(driver);
+ await sendToPage.check_pageIsLoaded();
+ await sendToPage.fillRecipient('0x2f318C334780961FB129D2a6c30D0763d9a5C970');
+ await sendToPage.fillAmount('1');
+ await sendToPage.goToNextScreen();
+};
+
+export const createDappTransaction = async (
+ driver: Driver,
+ override?: Partial,
+) => {
+ const testDapp = new TestDapp(driver);
+
+ await testDapp.request('eth_sendTransaction', [
+ {
+ data: '0x',
+ from: DEFAULT_FIXTURE_ACCOUNT,
+ maxFeePerGas: '0x0',
+ maxPriorityFeePerGas: '0x0',
+ to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970',
+ value: '0x38d7ea4c68000',
+ type: '0x2',
+ ...override,
+ },
+ ]);
+};
diff --git a/test/e2e/page-objects/pages/confirmations/legacy/navigation.ts b/test/e2e/page-objects/pages/confirmations/legacy/navigation.ts
new file mode 100644
index 000000000000..ab04f85a4a2e
--- /dev/null
+++ b/test/e2e/page-objects/pages/confirmations/legacy/navigation.ts
@@ -0,0 +1,57 @@
+import { Driver } from '../../../../webdriver/driver';
+
+class ConfirmationNavigation {
+ private driver: Driver;
+
+ private nextPageButton: string;
+
+ private previousPageButton: string;
+
+ private firstPageButton: string;
+
+ private lastPageButton: string;
+
+ private navigationTitle: string;
+
+ constructor(driver: Driver) {
+ this.driver = driver;
+ this.nextPageButton = '[data-testid="next-page"]';
+ this.previousPageButton = '[data-testid="previous-page"]';
+ this.firstPageButton = '[data-testid="first-page"]';
+ this.lastPageButton = '[data-testid="last-page"]';
+ this.navigationTitle = '.confirm-page-container-navigation';
+ }
+
+ async clickNextPage(): Promise {
+ await this.driver.clickElement(this.nextPageButton);
+ }
+
+ async clickPreviousPage(): Promise {
+ await this.driver.clickElement(this.previousPageButton);
+ }
+
+ async clickFirstPage(): Promise {
+ await this.driver.clickElement(this.firstPageButton);
+ }
+
+ async clickLastPage(): Promise {
+ await this.driver.clickElement(this.lastPageButton);
+ }
+
+ async check_pageNumbers(
+ currentPage: number,
+ totalPages: number,
+ ): Promise {
+ try {
+ await this.driver.findElement({
+ css: this.navigationTitle,
+ text: `${currentPage} of ${totalPages}`,
+ });
+ } catch (e) {
+ console.log('Timeout while waiting for navigation page numbers', e);
+ throw e;
+ }
+ }
+}
+
+export default ConfirmationNavigation;
diff --git a/test/e2e/page-objects/pages/test-dapp.ts b/test/e2e/page-objects/pages/test-dapp.ts
new file mode 100644
index 000000000000..8c2fe513ca10
--- /dev/null
+++ b/test/e2e/page-objects/pages/test-dapp.ts
@@ -0,0 +1,37 @@
+import { Driver } from '../../webdriver/driver';
+
+const DAPP_HOST_ADDRESS = '127.0.0.1:8080';
+const DAPP_URL = `http://${DAPP_HOST_ADDRESS}`;
+
+class TestDapp {
+ private driver: Driver;
+
+ constructor(driver: Driver) {
+ this.driver = driver;
+ }
+
+ async open({
+ contractAddress,
+ url = DAPP_URL,
+ }: {
+ contractAddress?: string;
+ url?: string;
+ }) {
+ const dappUrl = contractAddress
+ ? `${url}/?contract=${contractAddress}`
+ : url;
+
+ return await this.driver.openNewPage(dappUrl);
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ async request(method: string, params: any[]) {
+ await this.open({
+ url: `${DAPP_URL}/request?method=${method}¶ms=${JSON.stringify(
+ params,
+ )}`,
+ });
+ }
+}
+
+export default TestDapp;
diff --git a/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts b/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts
index 3d28afff5790..2a815a025d18 100644
--- a/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts
+++ b/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts
@@ -1,6 +1,10 @@
/* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */
+import { Mockttp } from 'mockttp';
import { openDapp, unlockWallet } from '../../../helpers';
+import { createDappTransaction } from '../../../page-objects/flows/transaction';
import GanacheContractAddressRegistry from '../../../seeder/ganache-contract-address-registry';
+import { Driver } from '../../../webdriver/driver';
+import { MockedEndpoint } from '../../../mock-e2e';
import {
assertAdvancedGasDetails,
confirmDepositTransaction,
@@ -90,8 +94,9 @@ describe('Confirmation Redesign Contract Interaction Component', function () {
redesignedConfirmationsEnabled: true,
isRedesignedConfirmationsDeveloperEnabled: true,
},
+ useTransactionSimulations: false,
})
- .withTransactionControllerOPLayer2Transaction()
+ .withNetworkControllerOnOptimism()
.build(),
ganacheOptions: {
...defaultGanacheOptionsForType2Transactions,
@@ -100,9 +105,11 @@ describe('Confirmation Redesign Contract Interaction Component', function () {
},
smartContract,
title: this.test?.fullTitle(),
+ testSpecificMock: mockOptimismOracle,
},
async ({ driver, contractRegistry }: TestSuiteArguments) => {
await unlockWallet(driver);
+ await createLayer2Transaction(driver);
const contractAddress = await (
contractRegistry as GanacheContractAddressRegistry
@@ -110,9 +117,7 @@ describe('Confirmation Redesign Contract Interaction Component', function () {
await openDapp(driver, contractAddress);
- await driver.switchToWindowWithTitle(
- WINDOW_TITLES.ExtensionInFullScreenView,
- );
+ await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
await toggleAdvancedDetails(driver);
@@ -279,3 +284,34 @@ describe('Confirmation Redesign Contract Interaction Component', function () {
});
});
});
+
+async function createLayer2Transaction(driver: Driver) {
+ await createDappTransaction(driver, {
+ data: '0x1234',
+ to: '0x581c3C1A2A4EBDE2A0Df29B5cf4c116E42945947',
+ });
+}
+
+async function mockOptimismOracle(
+ mockServer: Mockttp,
+): Promise {
+ return [
+ await mockServer
+ .forPost(/infura/u)
+ .withJsonBodyIncluding({
+ method: 'eth_call',
+ params: [{ to: '0x420000000000000000000000000000000000000f' }],
+ })
+ .thenCallback(() => {
+ return {
+ statusCode: 200,
+ json: {
+ jsonrpc: '2.0',
+ id: '1111111111111111',
+ result:
+ '0x0000000000000000000000000000000000000000000000000000000c895f9d79',
+ },
+ };
+ }),
+ ];
+}
diff --git a/test/e2e/tests/transaction/edit-gas-fee.spec.js b/test/e2e/tests/transaction/edit-gas-fee.spec.js
index 5a1f32a56411..85ae4da3a31f 100644
--- a/test/e2e/tests/transaction/edit-gas-fee.spec.js
+++ b/test/e2e/tests/transaction/edit-gas-fee.spec.js
@@ -1,4 +1,8 @@
const { strict: assert } = require('assert');
+const {
+ createInternalTransaction,
+} = require('../../page-objects/flows/transaction');
+
const {
withFixtures,
openDapp,
@@ -12,20 +16,18 @@ describe('Editing Confirm Transaction', function () {
it('allows selecting high, medium, low gas estimates on edit gas fee popover @no-mmi', async function () {
await withFixtures(
{
- fixtures: new FixtureBuilder()
- .withTransactionControllerTypeTwoTransaction()
- .build(),
+ fixtures: new FixtureBuilder().build(),
ganacheOptions: generateGanacheOptions({ hardfork: 'london' }),
title: this.test.fullTitle(),
},
async ({ driver }) => {
await unlockWallet(driver);
+ await createInternalTransaction(driver);
- const transactionAmounts = await driver.findElements(
- '.currency-display-component__text',
- );
- const transactionAmount = transactionAmounts[0];
- assert.equal(await transactionAmount.getText(), '1');
+ await driver.findElement({
+ css: '.currency-display-component__text',
+ text: '1',
+ });
// update estimates to high
await driver.clickElement('[data-testid="edit-gas-fee-icon"]');
@@ -87,20 +89,18 @@ describe('Editing Confirm Transaction', function () {
it('allows accessing advance gas fee popover from edit gas fee popover', async function () {
await withFixtures(
{
- fixtures: new FixtureBuilder()
- .withTransactionControllerTypeTwoTransaction()
- .build(),
+ fixtures: new FixtureBuilder().build(),
ganacheOptions: generateGanacheOptions({ hardfork: 'london' }),
title: this.test.fullTitle(),
},
async ({ driver }) => {
await unlockWallet(driver);
+ await createInternalTransaction(driver);
- const transactionAmounts = await driver.findElements(
- '.currency-display-component__text',
- );
- const transactionAmount = transactionAmounts[0];
- assert.equal(await transactionAmount.getText(), '1');
+ await driver.findElement({
+ css: '.currency-display-component__text',
+ text: '1',
+ });
// update estimates to high
await driver.clickElement('[data-testid="edit-gas-fee-icon"]');
diff --git a/test/e2e/tests/transaction/navigate-transactions.spec.js b/test/e2e/tests/transaction/navigate-transactions.spec.js
index 66e2665162a7..63170d027874 100644
--- a/test/e2e/tests/transaction/navigate-transactions.spec.js
+++ b/test/e2e/tests/transaction/navigate-transactions.spec.js
@@ -1,104 +1,61 @@
-const { strict: assert } = require('assert');
+const {
+ createDappTransaction,
+} = require('../../page-objects/flows/transaction');
+
+const {
+ default: ConfirmationNavigation,
+} = require('../../page-objects/pages/confirmations/legacy/navigation');
+
const {
withFixtures,
openDapp,
locateAccountBalanceDOM,
unlockWallet,
generateGanacheOptions,
+ WINDOW_TITLES,
} = require('../../helpers');
const FixtureBuilder = require('../../fixture-builder');
+const TRANSACTION_COUNT = 4;
+
describe('Navigate transactions', function () {
it('should navigate the unapproved transactions', async function () {
await withFixtures(
{
fixtures: new FixtureBuilder()
.withPreferencesControllerTxSimulationsDisabled()
- .withTransactionControllerMultipleTransactions()
+ .withPermissionControllerConnectedToTestDapp()
.build(),
ganacheOptions: generateGanacheOptions({ hardfork: 'london' }),
title: this.test.fullTitle(),
+ dapp: true,
},
async ({ driver }) => {
await unlockWallet(driver);
+ await createMultipleTransactions(driver, TRANSACTION_COUNT);
- // Wait until total amount is loaded to mitigate flakiness on reject
- await driver.findElement({
- tag: 'span',
- text: '3.0000315',
- });
+ const navigation = new ConfirmationNavigation(driver);
- // navigate transactions
- await driver.clickElement('[data-testid="next-page"]');
- let navigationElement = await driver.findElement(
- '.confirm-page-container-navigation',
- );
- let navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('2 of 4'),
- true,
- 'changed transaction right',
- );
- await driver.clickElement('[data-testid="next-page"]');
- navigationElement = await driver.findElement(
- '.confirm-page-container-navigation',
- );
- navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('3 of 4'),
- true,
- 'changed transaction right',
- );
- await driver.clickElement('[data-testid="next-page"]');
- navigationElement = await driver.findElement(
- '.confirm-page-container-navigation',
- );
- navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('4 of 4'),
- true,
- 'changed transaction right',
- );
- await driver.clickElement('[data-testid="first-page"]');
- navigationElement = await driver.findElement(
- '.confirm-page-container-navigation',
- );
- navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('1 of 4'),
- true,
- 'navigate to first transaction',
- );
- await driver.clickElement('[data-testid="last-page"]');
- navigationElement = await driver.findElement(
- '.confirm-page-container-navigation',
- );
- navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('4 of 4'),
- true,
- 'navigate to last transaction',
- );
- await driver.clickElement('[data-testid="previous-page"]');
- navigationElement = await driver.findElement(
- '.confirm-page-container-navigation',
- );
- navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('3 of 4'),
- true,
- 'changed transaction left',
- );
- await driver.clickElement('[data-testid="previous-page"]');
- navigationElement = await driver.findElement(
- '.confirm-page-container-navigation',
- );
- navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('2 of 4'),
- true,
- 'changed transaction left',
- );
+ await navigation.clickNextPage();
+ await navigation.check_pageNumbers(2, 4);
+
+ await navigation.clickNextPage();
+ await navigation.check_pageNumbers(3, 4);
+
+ await navigation.clickNextPage();
+ await navigation.check_pageNumbers(4, 4);
+
+ await navigation.clickFirstPage();
+ await navigation.check_pageNumbers(1, 4);
+
+ await navigation.clickLastPage();
+ await navigation.check_pageNumbers(4, 4);
+
+ await navigation.clickPreviousPage();
+ await navigation.check_pageNumbers(3, 4);
+
+ await navigation.clickPreviousPage();
+ await navigation.check_pageNumbers(2, 4);
},
);
});
@@ -110,48 +67,29 @@ describe('Navigate transactions', function () {
fixtures: new FixtureBuilder()
.withPermissionControllerConnectedToTestDapp()
.withPreferencesControllerTxSimulationsDisabled()
- .withTransactionControllerMultipleTransactions()
.build(),
ganacheOptions: generateGanacheOptions({ hardfork: 'london' }),
title: this.test.fullTitle(),
},
async ({ driver }) => {
await unlockWallet(driver);
+ await createMultipleTransactions(driver, TRANSACTION_COUNT);
- // Wait until total amount is loaded to mitigate flakiness on reject
- await driver.findElement({
- tag: 'span',
- text: '3.0000315',
- });
+ const navigation = new ConfirmationNavigation(driver);
- await driver.clickElement('[data-testid="next-page"]');
- let navigationElement = await driver.findElement(
- '.confirm-page-container-navigation',
- );
- let navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('2 of 4'),
- true,
- 'second transaction in focus',
+ await navigation.clickNextPage();
+ await navigation.check_pageNumbers(2, 4);
+
+ await driver.switchToWindowWithTitle(
+ WINDOW_TITLES.ExtensionInFullScreenView,
);
// add transaction
await openDapp(driver);
await driver.clickElement({ text: 'Send', tag: 'button' });
- await driver.waitUntilXWindowHandles(3);
- const windowHandles = await driver.getAllWindowHandles();
- const extension = windowHandles[0];
- await driver.switchToWindow(extension);
- navigationElement = await driver.waitForSelector({
- css: '.confirm-page-container-navigation',
- text: '2 of 5',
- });
- navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('2 of 5'),
- true,
- 'correct (same) transaction in focus',
- );
+ await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
+
+ await navigation.check_pageNumbers(2, 5);
},
);
});
@@ -161,32 +99,21 @@ describe('Navigate transactions', function () {
{
fixtures: new FixtureBuilder()
.withPreferencesControllerTxSimulationsDisabled()
- .withTransactionControllerMultipleTransactions()
+ .withPermissionControllerConnectedToTestDapp()
.build(),
ganacheOptions: generateGanacheOptions({ hardfork: 'london' }),
title: this.test.fullTitle(),
+ dapp: true,
},
async ({ driver }) => {
await unlockWallet(driver);
-
- // Wait until total amount is loaded to mitigate flakiness on reject
- await driver.findElement({
- tag: 'span',
- text: '3.0000315',
- });
+ await createMultipleTransactions(driver, TRANSACTION_COUNT);
// reject transaction
await driver.clickElement({ text: 'Reject', tag: 'button' });
- const navigationElement = await driver.waitForSelector({
- css: '.confirm-page-container-navigation',
- text: '1 of 3',
- });
- const navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('1 of 3'),
- true,
- 'transaction rejected',
- );
+
+ const navigation = new ConfirmationNavigation(driver);
+ await navigation.check_pageNumbers(1, 3);
},
);
});
@@ -196,32 +123,21 @@ describe('Navigate transactions', function () {
{
fixtures: new FixtureBuilder()
.withPreferencesControllerTxSimulationsDisabled()
- .withTransactionControllerMultipleTransactions()
+ .withPermissionControllerConnectedToTestDapp()
.build(),
ganacheOptions: generateGanacheOptions({ hardfork: 'london' }),
title: this.test.fullTitle(),
+ dapp: true,
},
async ({ driver }) => {
await unlockWallet(driver);
-
- // Wait until total amount is loaded to mitigate flakiness on reject
- await driver.findElement({
- tag: 'span',
- text: '3.0000315',
- });
+ await createMultipleTransactions(driver, TRANSACTION_COUNT);
// confirm transaction
await driver.clickElement({ text: 'Confirm', tag: 'button' });
- const navigationElement = await driver.waitForSelector({
- css: '.confirm-page-container-navigation',
- text: '1 of 3',
- });
- const navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('1 of 3'),
- true,
- 'transaction confirmed',
- );
+
+ const navigation = new ConfirmationNavigation(driver);
+ await navigation.check_pageNumbers(1, 3);
},
);
});
@@ -231,33 +147,39 @@ describe('Navigate transactions', function () {
{
fixtures: new FixtureBuilder()
.withPreferencesControllerTxSimulationsDisabled()
- .withTransactionControllerMultipleTransactions()
+ .withPermissionControllerConnectedToTestDapp()
.build(),
ganacheOptions: generateGanacheOptions({ hardfork: 'london' }),
title: this.test.fullTitle(),
+ dapp: true,
},
async ({ driver, ganacheServer }) => {
await unlockWallet(driver);
-
- // Wait until the confirmation screen is stabilized to mitigate flakiness on reject:
- // 1. Total amount is loaded
- await driver.findElement({
- tag: 'span',
- text: '3.0000315',
- });
- // 2. Gas timing is loaded
- await driver.findElement('[data-testid="gas-timing-time"]');
- // 3. Insufficient funds warning is not present
- await driver.assertElementNotPresent({
- text: 'You do not have enough ETH',
- tag: 'p',
- });
+ await createMultipleTransactions(driver, TRANSACTION_COUNT);
// reject transactions
await driver.clickElement({ text: 'Reject 4', tag: 'a' });
await driver.clickElement({ text: 'Reject all', tag: 'button' });
+
+ await driver.switchToWindowWithTitle(
+ WINDOW_TITLES.ExtensionInFullScreenView,
+ );
await locateAccountBalanceDOM(driver, ganacheServer);
},
);
});
});
+
+async function createMultipleTransactions(driver, count) {
+ for (let i = 0; i < count; i++) {
+ await createDappTransaction(driver);
+ }
+
+ await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
+
+ // Wait until total amount is loaded to mitigate flakiness on reject
+ await driver.findElement({
+ tag: 'span',
+ text: '0.001',
+ });
+}
diff --git a/test/e2e/tests/transaction/send-edit.spec.js b/test/e2e/tests/transaction/send-edit.spec.js
index 95e5b3235ebd..953f2ebf3569 100644
--- a/test/e2e/tests/transaction/send-edit.spec.js
+++ b/test/e2e/tests/transaction/send-edit.spec.js
@@ -1,4 +1,8 @@
const { strict: assert } = require('assert');
+const {
+ createInternalTransaction,
+} = require('../../page-objects/flows/transaction');
+
const {
defaultGanacheOptions,
withFixtures,
@@ -11,23 +15,23 @@ describe('Editing Confirm Transaction', function () {
it('goes back from confirm page to edit eth value, gas price and gas limit', async function () {
await withFixtures(
{
- fixtures: new FixtureBuilder()
- .withTransactionControllerTypeOneTransaction()
- .withConversionRateDisabled()
- .build(),
+ fixtures: new FixtureBuilder().withConversionRateDisabled().build(),
ganacheOptions: defaultGanacheOptions,
title: this.test.fullTitle(),
},
async ({ driver }) => {
await unlockWallet(driver);
- const transactionAmounts = await driver.findElements(
- '.currency-display-component__text',
- );
- const transactionAmount = transactionAmounts[0];
- assert.equal(await transactionAmount.getText(), '1');
+ await createInternalTransaction(driver);
- const transactionFee = transactionAmounts[1];
- assert.equal(await transactionFee.getText(), '0.00025');
+ await driver.findElement({
+ css: '.currency-display-component__text',
+ text: '1',
+ });
+
+ await driver.findElement({
+ css: '.currency-display-component__text',
+ text: '1.000042',
+ });
await driver.clickElement(
'.confirm-page-container-header__back-button',
@@ -86,23 +90,23 @@ describe('Editing Confirm Transaction', function () {
it('goes back from confirm page to edit eth value, baseFee, priorityFee and gas limit - 1559 V2', async function () {
await withFixtures(
{
- fixtures: new FixtureBuilder()
- .withTransactionControllerTypeTwoTransaction()
- .withConversionRateDisabled()
- .build(),
+ fixtures: new FixtureBuilder().withConversionRateDisabled().build(),
ganacheOptions: generateGanacheOptions({ hardfork: 'london' }),
title: this.test.fullTitle(),
},
async ({ driver }) => {
await unlockWallet(driver);
- const transactionAmounts = await driver.findElements(
- '.currency-display-component__text',
- );
- const transactionAmount = transactionAmounts[0];
- assert.equal(await transactionAmount.getText(), '1');
+ await createInternalTransaction(driver);
- const transactionFee = transactionAmounts[1];
- assert.equal(await transactionFee.getText(), '0.0000375');
+ await driver.findElement({
+ css: '.currency-display-component__text',
+ text: '1',
+ });
+
+ await driver.findElement({
+ css: '.currency-display-component__text',
+ text: '1.00043983',
+ });
await driver.clickElement(
'.confirm-page-container-header__back-button',
diff --git a/ui/__mocks__/ethereumjs-util.js b/ui/__mocks__/ethereumjs-util.js
new file mode 100644
index 000000000000..d7af4a81162c
--- /dev/null
+++ b/ui/__mocks__/ethereumjs-util.js
@@ -0,0 +1,6 @@
+// eslint-disable-next-line import/no-extraneous-dependencies, node/no-extraneous-require
+const util = require('ethereumjs-util');
+
+module.exports = {
+ ...util,
+};
diff --git a/yarn.lock b/yarn.lock
index 1c0a3d9ab60e..e6bf174ada48 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4870,7 +4870,7 @@ __metadata:
languageName: node
linkType: hard
-"@metamask/base-controller@npm:^6.0.0, @metamask/base-controller@npm:^6.0.1, @metamask/base-controller@npm:^6.0.2, @metamask/base-controller@npm:^6.0.3":
+"@metamask/base-controller@npm:^6.0.0, @metamask/base-controller@npm:^6.0.1, @metamask/base-controller@npm:^6.0.2":
version: 6.0.3
resolution: "@metamask/base-controller@npm:6.0.3"
dependencies:
@@ -4880,13 +4880,13 @@ __metadata:
languageName: node
linkType: hard
-"@metamask/base-controller@npm:^7.0.0":
- version: 7.0.0
- resolution: "@metamask/base-controller@npm:7.0.0"
+"@metamask/base-controller@npm:^7.0.0, @metamask/base-controller@npm:^7.0.1":
+ version: 7.0.1
+ resolution: "@metamask/base-controller@npm:7.0.1"
dependencies:
"@metamask/utils": "npm:^9.1.0"
immer: "npm:^9.0.6"
- checksum: 10/0ea307da4a7863224fd1fc83039165dbd06d2725922d4d4cf5854f5e7894e789a3c277f1e4592a38ae002de869217a26550f3b9687c259fc29153984dc5b4a4c
+ checksum: 10/774b6d68ac95a5ec187e890d321bede50065f8a6f1ba7b49a19f5971366274054ac0e401548b51d3b014d0bca5d650409fb554dd13ce120e7fb3495b4e8e67b1
languageName: node
linkType: hard
@@ -4923,9 +4923,9 @@ __metadata:
languageName: node
linkType: hard
-"@metamask/controller-utils@npm:^11.0.0, @metamask/controller-utils@npm:^11.0.1, @metamask/controller-utils@npm:^11.0.2, @metamask/controller-utils@npm:^11.1.0, @metamask/controller-utils@npm:^11.2.0":
- version: 11.2.0
- resolution: "@metamask/controller-utils@npm:11.2.0"
+"@metamask/controller-utils@npm:^11.0.0, @metamask/controller-utils@npm:^11.0.1, @metamask/controller-utils@npm:^11.0.2, @metamask/controller-utils@npm:^11.1.0, @metamask/controller-utils@npm:^11.2.0, @metamask/controller-utils@npm:^11.3.0":
+ version: 11.3.0
+ resolution: "@metamask/controller-utils@npm:11.3.0"
dependencies:
"@ethereumjs/util": "npm:^8.1.0"
"@metamask/eth-query": "npm:^4.0.0"
@@ -4936,7 +4936,7 @@ __metadata:
bn.js: "npm:^5.2.1"
eth-ens-namehash: "npm:^2.0.8"
fast-deep-equal: "npm:^3.1.3"
- checksum: 10/8c8630a635c5eeeb8ef46b14a12779a5005d8112668500bfb513186dee3f68b94dcf43ce6eddf42c38382828cd7ba28657b627d0eb617207a25b6ee78eae6b08
+ checksum: 10/3200228d1f4ea5fa095228db4e5050529caf0470e072382eb8f7571bb9b07515516ca9e846b7751388399d9ae967e4985dafd6120902ef6c998e98f4eb36d964
languageName: node
linkType: hard
@@ -6501,9 +6501,9 @@ __metadata:
languageName: node
linkType: hard
-"@metamask/transaction-controller@npm:^35.2.0":
- version: 35.2.0
- resolution: "@metamask/transaction-controller@npm:35.2.0"
+"@metamask/transaction-controller@npm:^37.0.0":
+ version: 37.0.0
+ resolution: "@metamask/transaction-controller@npm:37.0.0"
dependencies:
"@ethereumjs/common": "npm:^3.2.0"
"@ethereumjs/tx": "npm:^4.2.0"
@@ -6511,8 +6511,8 @@ __metadata:
"@ethersproject/abi": "npm:^5.7.0"
"@ethersproject/contracts": "npm:^5.7.0"
"@ethersproject/providers": "npm:^5.7.0"
- "@metamask/base-controller": "npm:^6.0.3"
- "@metamask/controller-utils": "npm:^11.0.2"
+ "@metamask/base-controller": "npm:^7.0.1"
+ "@metamask/controller-utils": "npm:^11.3.0"
"@metamask/eth-query": "npm:^4.0.0"
"@metamask/metamask-eth-abis": "npm:^3.1.1"
"@metamask/nonce-tracker": "npm:^6.0.0"
@@ -6528,9 +6528,9 @@ __metadata:
"@babel/runtime": ^7.23.9
"@metamask/accounts-controller": ^18.0.0
"@metamask/approval-controller": ^7.0.0
- "@metamask/gas-fee-controller": ^19.0.0
- "@metamask/network-controller": ^20.0.0
- checksum: 10/93af57d96860e4363b53ac1365742d77ca82689faf9ececca84309e15298a43a92e76a7ea3871b52b2a1785ff96e003db23e921ad6b4a4b65eddaa12d5edf570
+ "@metamask/gas-fee-controller": ^20.0.0
+ "@metamask/network-controller": ^21.0.0
+ checksum: 10/b4608260cb86ad1a867926b983a21050a2be899f17af909ad2403b5148eada348b0fbb3f7ecef9ebc7cf8d28c040ce4d6f5009709328cda00fab61e10fa94de6
languageName: node
linkType: hard
@@ -26062,7 +26062,7 @@ __metadata:
"@metamask/snaps-utils": "npm:^8.0.1"
"@metamask/test-bundler": "npm:^1.0.0"
"@metamask/test-dapp": "npm:^8.4.0"
- "@metamask/transaction-controller": "npm:^35.2.0"
+ "@metamask/transaction-controller": "npm:^37.0.0"
"@metamask/user-operation-controller": "npm:^13.0.0"
"@metamask/utils": "npm:^9.1.0"
"@ngraveio/bc-ur": "npm:^1.1.12"
From e7df8e2c0d9cb9d6a653d21809fb07f9e8d6310e Mon Sep 17 00:00:00 2001
From: Jyoti Puri
Date: Tue, 17 Sep 2024 16:32:45 +0530
Subject: [PATCH 05/37] fix: add memoization to confirm context (#27208)
---
.../confirmations/context/confirm/index.tsx | 24 ++++++++++++-------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/ui/pages/confirmations/context/confirm/index.tsx b/ui/pages/confirmations/context/confirm/index.tsx
index febab3453298..b8e2e1535fdb 100644
--- a/ui/pages/confirmations/context/confirm/index.tsx
+++ b/ui/pages/confirmations/context/confirm/index.tsx
@@ -2,6 +2,7 @@ import React, {
ReactElement,
createContext,
useContext,
+ useMemo,
useState,
} from 'react';
@@ -27,16 +28,21 @@ export const ConfirmContextProvider: React.FC<{
const { currentConfirmation } = useCurrentConfirmation();
syncConfirmPath(currentConfirmation);
+ const value = useMemo(
+ () => ({
+ currentConfirmation,
+ isScrollToBottomCompleted,
+ setIsScrollToBottomCompleted,
+ }),
+ [
+ currentConfirmation,
+ isScrollToBottomCompleted,
+ setIsScrollToBottomCompleted,
+ ],
+ );
+
return (
-
- {children}
-
+ {children}
);
};
From 270d2ad91fddb4f6c656eb8c0a08cb4f33a1b049 Mon Sep 17 00:00:00 2001
From: Jyoti Puri
Date: Tue, 17 Sep 2024 18:00:52 +0530
Subject: [PATCH 06/37] fix: selector getKnownMethodData should return empty
object if user has opted out for using 4Byte Resolution (#27203)
---
.../components/confirm/info/hooks/useFourByte.test.ts | 6 +++---
.../info/hooks/useKnownMethodDataInTransaction.test.ts | 6 +++---
.../info/shared/transaction-details/transaction-details.tsx | 2 +-
ui/selectors/selectors.js | 2 +-
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/ui/pages/confirmations/components/confirm/info/hooks/useFourByte.test.ts b/ui/pages/confirmations/components/confirm/info/hooks/useFourByte.test.ts
index 1c3d66570d8b..bdff31ac33e6 100644
--- a/ui/pages/confirmations/components/confirm/info/hooks/useFourByte.test.ts
+++ b/ui/pages/confirmations/components/confirm/info/hooks/useFourByte.test.ts
@@ -34,7 +34,7 @@ describe('useFourByte', () => {
expect(result.current.params).toEqual([]);
});
- it('returns undefined if resolution is turned off', () => {
+ it('returns empty object if resolution is turned off', () => {
const currentConfirmation = genUnapprovedContractInteractionConfirmation({
address: CONTRACT_INTERACTION_SENDER_ADDRESS,
txData: depositHexData,
@@ -54,7 +54,7 @@ describe('useFourByte', () => {
},
);
- expect(result.current).toBeUndefined();
+ expect(result.current).toEqual({});
});
it("returns undefined if it's not known even if resolution is enabled", () => {
@@ -75,6 +75,6 @@ describe('useFourByte', () => {
},
);
- expect(result.current).toBeUndefined();
+ expect(result.current).toEqual({});
});
});
diff --git a/ui/pages/confirmations/components/confirm/info/hooks/useKnownMethodDataInTransaction.test.ts b/ui/pages/confirmations/components/confirm/info/hooks/useKnownMethodDataInTransaction.test.ts
index 1c3d66570d8b..bdff31ac33e6 100644
--- a/ui/pages/confirmations/components/confirm/info/hooks/useKnownMethodDataInTransaction.test.ts
+++ b/ui/pages/confirmations/components/confirm/info/hooks/useKnownMethodDataInTransaction.test.ts
@@ -34,7 +34,7 @@ describe('useFourByte', () => {
expect(result.current.params).toEqual([]);
});
- it('returns undefined if resolution is turned off', () => {
+ it('returns empty object if resolution is turned off', () => {
const currentConfirmation = genUnapprovedContractInteractionConfirmation({
address: CONTRACT_INTERACTION_SENDER_ADDRESS,
txData: depositHexData,
@@ -54,7 +54,7 @@ describe('useFourByte', () => {
},
);
- expect(result.current).toBeUndefined();
+ expect(result.current).toEqual({});
});
it("returns undefined if it's not known even if resolution is enabled", () => {
@@ -75,6 +75,6 @@ describe('useFourByte', () => {
},
);
- expect(result.current).toBeUndefined();
+ expect(result.current).toEqual({});
});
});
diff --git a/ui/pages/confirmations/components/confirm/info/shared/transaction-details/transaction-details.tsx b/ui/pages/confirmations/components/confirm/info/shared/transaction-details/transaction-details.tsx
index f911c78fd343..e53387af325a 100644
--- a/ui/pages/confirmations/components/confirm/info/shared/transaction-details/transaction-details.tsx
+++ b/ui/pages/confirmations/components/confirm/info/shared/transaction-details/transaction-details.tsx
@@ -68,7 +68,7 @@ export const MethodDataRow = () => {
const { currentConfirmation } = useConfirmContext();
const methodData = useFourByte(currentConfirmation);
- if (!methodData) {
+ if (!methodData?.name) {
return null;
}
diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js
index 35bee7771dff..7d278675efd9 100644
--- a/ui/selectors/selectors.js
+++ b/ui/selectors/selectors.js
@@ -1262,7 +1262,7 @@ export function getKnownMethodData(state, data) {
const fourBytePrefix = prefixedData.slice(0, 10);
const { knownMethodData, use4ByteResolution } = state.metamask;
// If 4byte setting is off, we do not want to return the knownMethodData
- return use4ByteResolution ? knownMethodData?.[fourBytePrefix] : undefined;
+ return use4ByteResolution ? knownMethodData?.[fourBytePrefix] ?? {} : {};
}
export function getFeatureFlags(state) {
From 1386a58e9da45f9c12598003e7153d4a651f486f Mon Sep 17 00:00:00 2001
From: Jyoti Puri
Date: Tue, 17 Sep 2024 18:01:09 +0530
Subject: [PATCH 07/37] fix: Update max gas limit with value returned from
eth_estimateGas api if present (#27165)
---
.../advanced-gas-fee-gas-limit.js | 30 +++++++++---
.../advanced-gas-fee-gas-limit.test.js | 46 +++++++++++++++----
2 files changed, 61 insertions(+), 15 deletions(-)
diff --git a/ui/pages/confirmations/components/advanced-gas-fee-popover/advanced-gas-fee-gas-limit/advanced-gas-fee-gas-limit.js b/ui/pages/confirmations/components/advanced-gas-fee-popover/advanced-gas-fee-gas-limit/advanced-gas-fee-gas-limit.js
index 949aac299db2..848cdf381075 100644
--- a/ui/pages/confirmations/components/advanced-gas-fee-popover/advanced-gas-fee-gas-limit/advanced-gas-fee-gas-limit.js
+++ b/ui/pages/confirmations/components/advanced-gas-fee-popover/advanced-gas-fee-gas-limit/advanced-gas-fee-gas-limit.js
@@ -11,13 +11,12 @@ import FormField from '../../../../../components/ui/form-field';
import { useAdvancedGasFeePopoverContext } from '../context';
import { Text } from '../../../../../components/component-library';
import { IGNORE_GAS_LIMIT_CHAIN_IDS } from '../../../constants';
+import { hexToDecimal } from '../../../../../../shared/modules/conversion.utils';
-const validateGasLimit = (gasLimit, minimumGasLimitDec) => {
- return bnLessThan(gasLimit, minimumGasLimitDec) ||
- bnGreaterThan(gasLimit, MAX_GAS_LIMIT_DEC)
+const validateGasLimit = (gasLimit, minGasLimit, maxGasLimit) =>
+ bnLessThan(gasLimit, minGasLimit) || bnGreaterThan(gasLimit, maxGasLimit)
? 'editGasLimitOutOfBoundsV2'
: null;
-};
const AdvancedGasFeeGasLimit = () => {
const t = useI18nContext();
@@ -26,8 +25,15 @@ const AdvancedGasFeeGasLimit = () => {
const {
gasLimit: gasLimitInTransaction,
minimumGasLimitDec,
- transaction: { chainId },
+ transaction: { chainId, originalGasEstimate },
} = useGasFeeContext();
+ const originalGasEstimateDec =
+ originalGasEstimate !== undefined && hexToDecimal(originalGasEstimate);
+ const [maxGasLimit, setMaxGasLimit] = useState(
+ originalGasEstimateDec
+ ? Math.max(MAX_GAS_LIMIT_DEC, originalGasEstimateDec)
+ : MAX_GAS_LIMIT_DEC,
+ );
const [isEditing, setEditing] = useState(false);
const [gasLimit, setGasLimit] = useState(gasLimitInTransaction);
const [gasLimitError, setGasLimitError] = useState();
@@ -41,8 +47,9 @@ const AdvancedGasFeeGasLimit = () => {
if (IGNORE_GAS_LIMIT_CHAIN_IDS.includes(chainId)) {
return;
}
- const error = validateGasLimit(gasLimit, minimumGasLimitDec);
+ const error = validateGasLimit(gasLimit, minimumGasLimitDec, maxGasLimit);
setGasLimitError(error);
+ setEditing(isEditing === true ? isEditing : error !== null);
setErrorValue('gasLimit', error === 'editGasLimitOutOfBoundsV2');
}, [
chainId,
@@ -50,15 +57,24 @@ const AdvancedGasFeeGasLimit = () => {
minimumGasLimitDec,
setGasLimitInContext,
setErrorValue,
+ maxGasLimit,
+ isEditing,
+ t,
]);
+ useEffect(() => {
+ if (originalGasEstimateDec) {
+ setMaxGasLimit(Math.max(MAX_GAS_LIMIT_DEC, originalGasEstimateDec));
+ }
+ }, [minimumGasLimitDec, originalGasEstimateDec, setMaxGasLimit]);
+
if (isEditing) {
return (
({
const mockSelectedInternalAccount =
getSelectedInternalAccountFromMockState(mockState);
-const render = async (contextProps) => {
+const render = async (contextProps, transaction) => {
const store = configureStore({
metamask: {
...mockState.metamask,
@@ -57,10 +57,12 @@ const render = async (contextProps) => {
async () =>
(result = renderWithProvider(
@@ -117,14 +119,42 @@ describe('AdvancedGasFeeGasLimit', () => {
});
it('should validate gas limit against minimumGasLimit it is passed to context', async () => {
- await render({ minimumGasLimit: '0x7530' });
+ await render({ minimumGasLimit: '0x5208' });
fireEvent.click(screen.queryByText('Edit'));
fireEvent.change(document.getElementsByTagName('input')[0], {
- target: { value: 25000 },
+ target: { value: 2500 },
});
expect(
screen.queryByText(
- `Gas limit must be greater than 29999 and less than ${MAX_GAS_LIMIT_DEC}`,
+ `Gas limit must be greater than 20999 and less than ${MAX_GAS_LIMIT_DEC}`,
+ ),
+ ).toBeInTheDocument();
+ });
+
+ it('should replace maximum gas limit with originalGasEstimate if it is greater than maximum gas limit', async () => {
+ await render(
+ { minimumGasLimit: '0x7530' },
+ {
+ chainId: '0x5',
+ id: 8393540981007587,
+ time: 1536268017676,
+ status: 'unapproved',
+ loadingDefaults: false,
+ originalGasEstimate: '0x78D9B2',
+ txParams: {
+ data: '0xa9059cbb000000000000000000000000b19ac54efa18cc3a14a5b821bfec73d284bf0c5e0000000000000000000000000000000000000000000000003782dace9d900000',
+ from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
+ to: '0xc42edfcc21ed14dda456aa0756c153f7985d8813',
+ value: '0x0',
+ gas: '0x3b9aca00',
+ gasPrice: '0x3b9aca00',
+ },
+ origin: 'metamask',
+ },
+ );
+ expect(
+ screen.queryByText(
+ `Gas limit must be greater than 29999 and less than 7920050`,
),
).toBeInTheDocument();
});
From 56c23fc04bf102ef2bdc595b6675af248a24f32a Mon Sep 17 00:00:00 2001
From: "devin-ai-integration[bot]"
<158243242+devin-ai-integration[bot]@users.noreply.github.com>
Date: Tue, 17 Sep 2024 15:19:14 +0200
Subject: [PATCH 08/37] test: [POM] create AccountListPage for e2e tests and
migrate 4 test files to POM and TS (#27201)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
This pull request creates the AccountListPage class for the E2E tests
page object model and migrates 4 test files in `test/e2e/tests/account`
to POM **and** TypeScript, with enhanced log messages.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27155?quickstart=1)
## **Related issues**
Fixes: #27163
## **Manual testing steps**
Check code readability, make sure tests pass.
## **Screenshots/Recordings**
### **Before**
### **After**
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.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/develop/.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.
---------
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Chloe Gao
Co-authored-by: chloeYue <105063779+chloeYue@users.noreply.github.com>
---
.../page-objects/pages/account-list-page.ts | 92 +++++++++++++++++++
test/e2e/page-objects/pages/header-navbar.ts | 11 +++
test/e2e/page-objects/pages/homepage.ts | 8 ++
.../tests/account/account-hide-unhide.spec.js | 63 -------------
.../tests/account/account-hide-unhide.spec.ts | 35 +++++++
.../tests/account/account-pin-unpin.spec.js | 71 --------------
.../tests/account/account-pin-unpin.spec.ts | 67 ++++++++++++++
test/e2e/tests/account/lock-account.spec.js | 37 --------
test/e2e/tests/account/lock-account.spec.ts | 24 +++++
.../{lockdown.spec.js => lockdown.spec.ts} | 28 +++---
.../account-list-item/account-list-item.js | 1 +
11 files changed, 251 insertions(+), 186 deletions(-)
create mode 100644 test/e2e/page-objects/pages/account-list-page.ts
delete mode 100644 test/e2e/tests/account/account-hide-unhide.spec.js
create mode 100644 test/e2e/tests/account/account-hide-unhide.spec.ts
delete mode 100644 test/e2e/tests/account/account-pin-unpin.spec.js
create mode 100644 test/e2e/tests/account/account-pin-unpin.spec.ts
delete mode 100644 test/e2e/tests/account/lock-account.spec.js
create mode 100644 test/e2e/tests/account/lock-account.spec.ts
rename test/e2e/tests/account/{lockdown.spec.js => lockdown.spec.ts} (76%)
diff --git a/test/e2e/page-objects/pages/account-list-page.ts b/test/e2e/page-objects/pages/account-list-page.ts
new file mode 100644
index 000000000000..8550c092b23c
--- /dev/null
+++ b/test/e2e/page-objects/pages/account-list-page.ts
@@ -0,0 +1,92 @@
+import { Driver } from '../../webdriver/driver';
+
+class AccountListPage {
+ private driver: Driver;
+
+ private accountListItem: object;
+
+ private accountOptionsMenuButton: string;
+
+ private hideUnhideAccountButton: string;
+
+ private hiddenAccountsList: string;
+
+ private hiddenAccountOptionsMenuButton: string;
+
+ private pinnedIcon: string;
+
+ private pinUnpinAccountButton: string;
+
+ constructor(driver: Driver) {
+ this.driver = driver;
+ this.accountOptionsMenuButton =
+ '[data-testid="account-list-item-menu-button"]';
+ this.hideUnhideAccountButton = '[data-testid="account-list-menu-hide"]';
+ this.pinUnpinAccountButton = '[data-testid="account-list-menu-pin"]';
+ this.hiddenAccountsList = '[data-testid="hidden-accounts-list"]';
+ this.pinnedIcon = '[data-testid="account-pinned-icon"]';
+ this.accountListItem = {
+ text: 'Account',
+ css: '.multichain-account-menu-popover__list--menu-item',
+ };
+ this.hiddenAccountOptionsMenuButton =
+ '.multichain-account-menu-popover__list--menu-item-hidden-account [data-testid="account-list-item-menu-button"]';
+ }
+
+ async hideAccount(): Promise {
+ console.log(`Hide account in account list`);
+ await this.driver.clickElement(this.hideUnhideAccountButton);
+ }
+
+ async openAccountOptionsMenu(): Promise {
+ console.log(`Open account option menu`);
+ await this.driver.clickElement(this.accountOptionsMenuButton);
+ }
+
+ async openHiddenAccountOptions(): Promise {
+ console.log(`Open hidden accounts options menu`);
+ await this.driver.clickElement(this.hiddenAccountOptionsMenuButton);
+ }
+
+ async openHiddenAccountsList(): Promise {
+ console.log(`Open hidden accounts option menu`);
+ await this.driver.clickElement(this.hiddenAccountsList);
+ }
+
+ async pinAccount(): Promise {
+ console.log(`Pin account in account list`);
+ await this.driver.clickElement(this.pinUnpinAccountButton);
+ }
+
+ async unhideAccount(): Promise {
+ console.log(`Unhide account in account list`);
+ await this.driver.clickElement(this.hideUnhideAccountButton);
+ }
+
+ async unpinAccount(): Promise {
+ console.log(`Unpin account in account list`);
+ await this.driver.clickElement(this.pinUnpinAccountButton);
+ }
+
+ async check_accountIsDisplayed(): Promise {
+ console.log(`Check that account is displayed in account list`);
+ await this.driver.waitForSelector(this.accountListItem);
+ }
+
+ async check_accountIsPinned(): Promise {
+ console.log(`Check that account is pinned`);
+ await this.driver.waitForSelector(this.pinnedIcon);
+ }
+
+ async check_accountIsUnpinned(): Promise {
+ console.log(`Check that account is unpinned`);
+ await this.driver.assertElementNotPresent(this.pinnedIcon);
+ }
+
+ async check_hiddenAccountsListExists(): Promise {
+ console.log(`Check that hidden accounts list is displayed in account list`);
+ await this.driver.waitForSelector(this.hiddenAccountsList);
+ }
+}
+
+export default AccountListPage;
diff --git a/test/e2e/page-objects/pages/header-navbar.ts b/test/e2e/page-objects/pages/header-navbar.ts
index add85e88b7b7..a6d58b6b1946 100644
--- a/test/e2e/page-objects/pages/header-navbar.ts
+++ b/test/e2e/page-objects/pages/header-navbar.ts
@@ -5,14 +5,25 @@ class HeaderNavbar {
private accountMenuButton: string;
+ private accountOptionMenu: string;
+
+ private lockMetaMaskButton: string;
+
constructor(driver: Driver) {
this.driver = driver;
this.accountMenuButton = '[data-testid="account-menu-icon"]';
+ this.accountOptionMenu = '[data-testid="account-options-menu-button"]';
+ this.lockMetaMaskButton = '[data-testid="global-menu-lock"]';
}
async openAccountMenu(): Promise {
await this.driver.clickElement(this.accountMenuButton);
}
+
+ async lockMetaMask(): Promise {
+ await this.driver.clickElement(this.accountOptionMenu);
+ await this.driver.clickElement(this.lockMetaMaskButton);
+ }
}
export default HeaderNavbar;
diff --git a/test/e2e/page-objects/pages/homepage.ts b/test/e2e/page-objects/pages/homepage.ts
index 5e596021a449..92c5e34f2a0e 100644
--- a/test/e2e/page-objects/pages/homepage.ts
+++ b/test/e2e/page-objects/pages/homepage.ts
@@ -20,6 +20,8 @@ class HomePage {
private transactionAmountsInActivity: string;
+ private accountMenuButton: string;
+
public headerNavbar: HeaderNavbar;
constructor(driver: Driver) {
@@ -36,6 +38,7 @@ class HomePage {
this.completedTransactions = '[data-testid="activity-list-item"]';
this.transactionAmountsInActivity =
'[data-testid="transaction-list-item-primary-currency"]';
+ this.accountMenuButton = '[data-testid="account-menu-icon"]';
}
async check_pageIsLoaded(): Promise {
@@ -81,6 +84,11 @@ class HomePage {
await this.driver.clickElement(this.activityTab);
}
+ async openAccountMenu(): Promise {
+ console.log(`Opening account menu`);
+ await this.driver.clickElement(this.accountMenuButton);
+ }
+
/**
* This function checks if the specified number of confirmed transactions are displayed in the activity list on homepage.
* It waits up to 10 seconds for the expected number of confirmed transactions to be visible.
diff --git a/test/e2e/tests/account/account-hide-unhide.spec.js b/test/e2e/tests/account/account-hide-unhide.spec.js
deleted file mode 100644
index 803954ea38e3..000000000000
--- a/test/e2e/tests/account/account-hide-unhide.spec.js
+++ /dev/null
@@ -1,63 +0,0 @@
-const { strict: assert } = require('assert');
-const {
- defaultGanacheOptions,
- withFixtures,
- unlockWallet,
-} = require('../../helpers');
-const FixtureBuilder = require('../../fixture-builder');
-
-describe('Account list - hide/unhide functionality - ', function () {
- it('hide account by clicking hide button', async function () {
- await withFixtures(
- {
- fixtures: new FixtureBuilder().build(),
- ganacheOptions: defaultGanacheOptions,
- 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-hide"]');
- const hiddenAccounts = await driver.findElement(
- '.hidden-accounts-list',
- );
- assert.equal(await hiddenAccounts.isDisplayed(), true);
- },
- );
- });
-
- it('unhide account by clicking show account button', async function () {
- await withFixtures(
- {
- fixtures: new FixtureBuilder().build(),
- ganacheOptions: defaultGanacheOptions,
- 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-hide"]');
-
- await driver.clickElement('.hidden-accounts-list');
-
- await driver.clickElement(
- '.multichain-account-menu-popover__list--menu-item-hidden-account [data-testid="account-list-item-menu-button"]',
- );
- await driver.clickElement('[data-testid="account-list-menu-hide"]');
-
- const accounts = await driver.findElement(
- '.multichain-account-menu-popover__list--menu-item',
- );
- assert.equal(await accounts.isDisplayed(), true);
- },
- );
- });
-});
diff --git a/test/e2e/tests/account/account-hide-unhide.spec.ts b/test/e2e/tests/account/account-hide-unhide.spec.ts
new file mode 100644
index 000000000000..19523b0ab0ce
--- /dev/null
+++ b/test/e2e/tests/account/account-hide-unhide.spec.ts
@@ -0,0 +1,35 @@
+import { Suite } from 'mocha';
+import { Driver } from '../../webdriver/driver';
+import { withFixtures, defaultGanacheOptions } from '../../helpers';
+import FixtureBuilder from '../../fixture-builder';
+import { loginWithBalanceValidation } from '../../page-objects/flows/login.flow';
+import HomePage from '../../page-objects/pages/homepage';
+import AccountListPage from '../../page-objects/pages/account-list-page';
+
+describe('Account list - hide/unhide functionality', function (this: Suite) {
+ it('hide and unhide account by clicking hide and unhide button', async function () {
+ await withFixtures(
+ {
+ fixtures: new FixtureBuilder().build(),
+ ganacheOptions: defaultGanacheOptions,
+ title: this.test?.fullTitle(),
+ },
+ async ({ driver }: { driver: Driver }) => {
+ await loginWithBalanceValidation(driver);
+ new HomePage(driver).openAccountMenu();
+
+ // hide account
+ const accountListPage = new AccountListPage(driver);
+ await accountListPage.openAccountOptionsMenu();
+ await accountListPage.hideAccount();
+ await accountListPage.check_hiddenAccountsListExists();
+
+ // unhide account
+ await accountListPage.openHiddenAccountsList();
+ await accountListPage.openHiddenAccountOptions();
+ await accountListPage.unhideAccount();
+ await accountListPage.check_accountIsDisplayed();
+ },
+ );
+ });
+});
diff --git a/test/e2e/tests/account/account-pin-unpin.spec.js b/test/e2e/tests/account/account-pin-unpin.spec.js
deleted file mode 100644
index dc4b6d564506..000000000000
--- a/test/e2e/tests/account/account-pin-unpin.spec.js
+++ /dev/null
@@ -1,71 +0,0 @@
-const { strict: assert } = require('assert');
-const {
- defaultGanacheOptions,
- withFixtures,
- unlockWallet,
-} = require('../../helpers');
-const FixtureBuilder = require('../../fixture-builder');
-
-describe('Account list - pin/unpin functionality - ', function () {
- it('pin and unpin account by clicking the pin/unpin button', async function () {
- await withFixtures(
- {
- fixtures: new FixtureBuilder().build(),
- ganacheOptions: defaultGanacheOptions,
- title: this.test.fullTitle(),
- },
- async ({ driver }) => {
- const pinnedIconSelector = '.account-pinned-icon';
- await unlockWallet(driver);
-
- // pin account
- 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-pin"]');
- const pinnedIcon = await driver.findElement(pinnedIconSelector);
- assert.equal(await pinnedIcon.isDisplayed(), true);
-
- // unpin account
- await driver.clickElement(
- '[data-testid="account-list-item-menu-button"]',
- );
- await driver.clickElement('[data-testid="account-list-menu-pin"]');
-
- await driver.assertElementNotPresent(pinnedIconSelector, {
- waitAtLeastGuard: 200, // A waitAtLeastGuard of 200ms is the best choice here
- });
- },
- );
- });
-
- it('account once hidden should be unpinned and remain so even if revealed again', async function () {
- await withFixtures(
- {
- fixtures: new FixtureBuilder().build(),
- ganacheOptions: defaultGanacheOptions,
- 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-pin"]');
- const pinnedIcon = await driver.findElement('.account-pinned-icon');
- assert.equal(await pinnedIcon.isDisplayed(), true);
- await driver.clickElement(
- '[data-testid="account-list-item-menu-button"]',
- );
- await driver.clickElement('[data-testid="account-list-menu-hide"]');
- const hiddenAccounts = await driver.findElement(
- '.hidden-accounts-list',
- );
- assert.equal(await hiddenAccounts.isDisplayed(), true);
- },
- );
- });
-});
diff --git a/test/e2e/tests/account/account-pin-unpin.spec.ts b/test/e2e/tests/account/account-pin-unpin.spec.ts
new file mode 100644
index 000000000000..a37859dfa6a9
--- /dev/null
+++ b/test/e2e/tests/account/account-pin-unpin.spec.ts
@@ -0,0 +1,67 @@
+import { Suite } from 'mocha';
+import { Driver } from '../../webdriver/driver';
+import { withFixtures, defaultGanacheOptions } from '../../helpers';
+import FixtureBuilder from '../../fixture-builder';
+import { loginWithBalanceValidation } from '../../page-objects/flows/login.flow';
+import HomePage from '../../page-objects/pages/homepage';
+import AccountListPage from '../../page-objects/pages/account-list-page';
+
+describe('Account list - pin/unpin functionality', function (this: Suite) {
+ it('pin and unpin account by clicking the pin/unpin button', async function () {
+ await withFixtures(
+ {
+ fixtures: new FixtureBuilder().build(),
+ ganacheOptions: defaultGanacheOptions,
+ title: this.test?.fullTitle(),
+ },
+ async ({ driver }: { driver: Driver }) => {
+ await loginWithBalanceValidation(driver);
+ new HomePage(driver).openAccountMenu();
+
+ // pin account
+ const accountListPage = new AccountListPage(driver);
+ await accountListPage.openAccountOptionsMenu();
+ await accountListPage.pinAccount();
+ await accountListPage.check_accountIsPinned();
+
+ // unpin account
+ await accountListPage.openAccountOptionsMenu();
+ await accountListPage.unpinAccount();
+ await accountListPage.check_accountIsUnpinned();
+ },
+ );
+ });
+
+ it('account once hidden should be unpinned and remain so even if revealed again', async function () {
+ await withFixtures(
+ {
+ fixtures: new FixtureBuilder().build(),
+ ganacheOptions: defaultGanacheOptions,
+ title: this.test?.fullTitle(),
+ },
+ async ({ driver }: { driver: Driver }) => {
+ await loginWithBalanceValidation(driver);
+ new HomePage(driver).openAccountMenu();
+
+ // pin account
+ const accountListPage = new AccountListPage(driver);
+ await accountListPage.openAccountOptionsMenu();
+ await accountListPage.pinAccount();
+ await accountListPage.check_accountIsPinned();
+
+ // hide the same account and check the account is unpinned automatically
+ await accountListPage.openAccountOptionsMenu();
+ await accountListPage.hideAccount();
+ await accountListPage.check_hiddenAccountsListExists();
+ await accountListPage.check_accountIsUnpinned();
+
+ // unhide the same account and check the account is still unpinned
+ await accountListPage.openHiddenAccountsList();
+ await accountListPage.openHiddenAccountOptions();
+ await accountListPage.unhideAccount();
+ await accountListPage.check_accountIsDisplayed();
+ await accountListPage.check_accountIsUnpinned();
+ },
+ );
+ });
+});
diff --git a/test/e2e/tests/account/lock-account.spec.js b/test/e2e/tests/account/lock-account.spec.js
deleted file mode 100644
index d384ff0020ae..000000000000
--- a/test/e2e/tests/account/lock-account.spec.js
+++ /dev/null
@@ -1,37 +0,0 @@
-const { strict: assert } = require('assert');
-const {
- defaultGanacheOptions,
- withFixtures,
- unlockWallet,
-} = require('../../helpers');
-const FixtureBuilder = require('../../fixture-builder');
-
-describe('Lock and unlock', function () {
- it('successfully unlocks after lock', async function () {
- await withFixtures(
- {
- fixtures: new FixtureBuilder().build(),
- ganacheOptions: defaultGanacheOptions,
- title: this.test.fullTitle(),
- },
- async ({ driver }) => {
- await unlockWallet(driver);
-
- await driver.clickElement(
- '[data-testid="account-options-menu-button"]',
- );
- const lockButton = await driver.findClickableElement(
- '[data-testid="global-menu-lock"]',
- );
- assert.equal(await lockButton.getText(), 'Lock MetaMask');
- await lockButton.click();
- await unlockWallet(driver);
-
- const walletBalance = await driver.findElement(
- '.eth-overview__primary-balance',
- );
- assert.equal(/^25\s*ETH$/u.test(await walletBalance.getText()), true);
- },
- );
- });
-});
diff --git a/test/e2e/tests/account/lock-account.spec.ts b/test/e2e/tests/account/lock-account.spec.ts
new file mode 100644
index 000000000000..c4cc914978cb
--- /dev/null
+++ b/test/e2e/tests/account/lock-account.spec.ts
@@ -0,0 +1,24 @@
+import { Suite } from 'mocha';
+import { defaultGanacheOptions, withFixtures } from '../../helpers';
+import FixtureBuilder from '../../fixture-builder';
+import HomePage from '../../page-objects/pages/homepage';
+import { Driver } from '../../webdriver/driver';
+import { loginWithBalanceValidation } from '../../page-objects/flows/login.flow';
+
+describe('Lock and unlock', function (this: Suite) {
+ it('successfully unlocks after lock', async function () {
+ await withFixtures(
+ {
+ fixtures: new FixtureBuilder().build(),
+ ganacheOptions: defaultGanacheOptions,
+ title: this.test?.fullTitle(),
+ },
+ async ({ driver }: { driver: Driver }) => {
+ await loginWithBalanceValidation(driver);
+ const homePage = new HomePage(driver);
+ await homePage.headerNavbar.lockMetaMask();
+ await loginWithBalanceValidation(driver);
+ },
+ );
+ });
+});
diff --git a/test/e2e/tests/account/lockdown.spec.js b/test/e2e/tests/account/lockdown.spec.ts
similarity index 76%
rename from test/e2e/tests/account/lockdown.spec.js
rename to test/e2e/tests/account/lockdown.spec.ts
index c0d5d52ee412..4307e1e33d6e 100644
--- a/test/e2e/tests/account/lockdown.spec.js
+++ b/test/e2e/tests/account/lockdown.spec.ts
@@ -1,13 +1,13 @@
-const { strict: assert } = require('assert');
-const { Browser } = require('selenium-webdriver');
-const {
+import { strict as assert } from 'assert';
+import { Browser } from 'selenium-webdriver';
+import {
getGlobalProperties,
testIntrinsic,
-} = require('../../../helpers/protect-intrinsics-helpers');
-const { convertToHexValue, withFixtures } = require('../../helpers');
-const { PAGES } = require('../../webdriver/driver');
-const FixtureBuilder = require('../../fixture-builder');
-const { isManifestV3 } = require('../../../../shared/modules/mv3.utils');
+} from '../../../helpers/protect-intrinsics-helpers';
+import { convertToHexValue, withFixtures } from '../../helpers';
+import { PAGES, Driver } from '../../webdriver/driver';
+import FixtureBuilder from '../../fixture-builder';
+import { isManifestV3 } from '../../../../shared/modules/mv3.utils';
const isFirefox = process.env.SELENIUM_BROWSER === Browser.FIREFOX;
@@ -52,7 +52,7 @@ try {
}
`;
-describe('lockdown', function () {
+describe('lockdown', function (this: Mocha.Suite) {
const ganacheOptions = {
accounts: [
{
@@ -66,12 +66,11 @@ describe('lockdown', function () {
it('the UI environment is locked down', async function () {
await withFixtures(
{
- // The fixtures used here is arbitrary. Any fixture would do.
fixtures: new FixtureBuilder().build(),
ganacheOptions,
- title: this.test.fullTitle(),
+ title: this.test?.fullTitle(),
},
- async ({ driver }) => {
+ async ({ driver }: { driver: Driver }) => {
await driver.navigate(PAGES.HOME);
assert.equal(
await driver.executeScript(lockdownTestScript),
@@ -85,12 +84,11 @@ describe('lockdown', function () {
it('the background environment is locked down', async function () {
await withFixtures(
{
- // The fixtures used here is arbitrary. Any fixture would do.
fixtures: new FixtureBuilder().build(),
ganacheOptions,
- title: this.test.fullTitle(),
+ title: this.test?.fullTitle(),
},
- async ({ driver }) => {
+ async ({ driver }: { driver: Driver }) => {
if (isManifestV3) {
// TODO: add logic for testing the Service-Worker on MV3
await driver.navigate(PAGES.OFFSCREEN);
diff --git a/ui/components/multichain/account-list-item/account-list-item.js b/ui/components/multichain/account-list-item/account-list-item.js
index 0991b77c3b29..7669ab99cf62 100644
--- a/ui/components/multichain/account-list-item/account-list-item.js
+++ b/ui/components/multichain/account-list-item/account-list-item.js
@@ -255,6 +255,7 @@ const AccountListItem = ({
name={IconName.Pin}
size={IconSize.Xs}
className="account-pinned-icon"
+ data-testid="account-pinned-icon"
/>
) : null}
{isHidden ? (
From a46faacf168d68778e77d7033ef261f919e880e2 Mon Sep 17 00:00:00 2001
From: Danica Shen
Date: Tue, 17 Sep 2024 15:15:42 +0100
Subject: [PATCH 09/37] chore(3210): deprecated `Application open` metric event
(#27102)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
Refer to [Slack
thread](https://consensys.slack.com/archives/G01FXS64DFA/p1725383758137349?thread_ts=1724763550.024349&cid=G01FXS64DFA),
it is discovered that `Application Opened` event is only emitted during
the on-boarding flow, not every time the application is opened. And
further is discussed in [this
issue](https://github.com/MetaMask/MetaMask-planning/issues/2847). In
the end the decision made was to remove this event from codebase
completely
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27102?quickstart=1)
## **Related issues**
Fixes: https://github.com/MetaMask/MetaMask-planning/issues/3210
## **Manual testing steps**
1. Go to this page...
2.
3.
## **Screenshots/Recordings**
### **Before**
### **After**
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
---
shared/constants/metametrics.ts | 1 -
.../onboarding/wallet-created.test.tsx | 31 -------------------
.../pin-extension/pin-extension.js | 21 +------------
3 files changed, 1 insertion(+), 52 deletions(-)
diff --git a/shared/constants/metametrics.ts b/shared/constants/metametrics.ts
index 502f166c8e91..daec305bfb11 100644
--- a/shared/constants/metametrics.ts
+++ b/shared/constants/metametrics.ts
@@ -569,7 +569,6 @@ export enum MetaMetricsEventName {
OnboardingWalletSecurityPhraseWrittenDown = 'SRP Backup Confirm Display',
OnboardingWalletSecurityPhraseConfirmed = 'SRP Backup Confirmed',
OnboardingWalletCreationComplete = 'Wallet Created',
- OnboardingWalletSetupComplete = 'Application Opened',
OnboardingWalletAdvancedSettings = 'Settings Updated',
OnboardingWalletImportAttempted = 'Wallet Import Attempted',
OnboardingWalletVideoPlay = 'SRP Intro Video Played',
diff --git a/test/integration/onboarding/wallet-created.test.tsx b/test/integration/onboarding/wallet-created.test.tsx
index fae425ad8a35..36ff7c8d3ecf 100644
--- a/test/integration/onboarding/wallet-created.test.tsx
+++ b/test/integration/onboarding/wallet-created.test.tsx
@@ -87,36 +87,5 @@ describe('Wallet Created Events', () => {
expect(completeOnboardingBackgroundRequest).toBeTruthy();
});
-
- await waitFor(() => {
- const OnboardingWalletSetupCompleteEvent =
- mockedBackgroundConnection.submitRequestToBackground.mock.calls?.find(
- (call) => {
- if (call[0] === 'trackMetaMetricsEvent') {
- const callArgs = call[1] as unknown as Record[];
-
- return (
- callArgs[0].event ===
- MetaMetricsEventName.OnboardingWalletSetupComplete
- );
- }
-
- return false;
- },
- );
-
- expect(OnboardingWalletSetupCompleteEvent?.[1]).toEqual(
- expect.arrayContaining([
- expect.objectContaining({
- category: MetaMetricsEventCategory.Onboarding,
- event: MetaMetricsEventName.OnboardingWalletSetupComplete,
- properties: {
- wallet_setup_type: 'new',
- new_wallet: true,
- },
- }),
- ]),
- );
- });
});
});
diff --git a/ui/pages/onboarding-flow/pin-extension/pin-extension.js b/ui/pages/onboarding-flow/pin-extension/pin-extension.js
index ab7fbd2d66bb..216bb1416cdf 100644
--- a/ui/pages/onboarding-flow/pin-extension/pin-extension.js
+++ b/ui/pages/onboarding-flow/pin-extension/pin-extension.js
@@ -1,12 +1,11 @@
import React, {
///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask)
useState,
- useContext,
///: END:ONLY_INCLUDE_IF
} from 'react';
import { useHistory } from 'react-router-dom';
///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask)
-import { useDispatch, useSelector } from 'react-redux';
+import { useDispatch } from 'react-redux';
import { Carousel } from 'react-responsive-carousel';
import { setCompletedOnboarding } from '../../../store/actions';
///: END:ONLY_INCLUDE_IF
@@ -31,13 +30,6 @@ import OnboardingPinMmiBillboard from '../../institutional/pin-mmi-billboard/pin
///: END:ONLY_INCLUDE_IF
import { Text } from '../../../components/component-library';
///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask)
-import { MetaMetricsContext } from '../../../contexts/metametrics';
-import { getFirstTimeFlowType } from '../../../selectors';
-import {
- MetaMetricsEventCategory,
- MetaMetricsEventName,
-} from '../../../../shared/constants/metametrics';
-import { FirstTimeFlowType } from '../../../../shared/constants/onboarding';
import OnboardingPinBillboard from './pin-billboard';
///: END:ONLY_INCLUDE_IF
@@ -47,8 +39,6 @@ export default function OnboardingPinExtension() {
///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask)
const [selectedIndex, setSelectedIndex] = useState(0);
const dispatch = useDispatch();
- const trackEvent = useContext(MetaMetricsContext);
- const firstTimeFlowType = useSelector(getFirstTimeFlowType);
///: END:ONLY_INCLUDE_IF
///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask)
@@ -57,15 +47,6 @@ export default function OnboardingPinExtension() {
setSelectedIndex(1);
} else {
await dispatch(setCompletedOnboarding());
- trackEvent({
- category: MetaMetricsEventCategory.Onboarding,
- event: MetaMetricsEventName.OnboardingWalletSetupComplete,
- properties: {
- wallet_setup_type:
- firstTimeFlowType === FirstTimeFlowType.import ? 'import' : 'new',
- new_wallet: firstTimeFlowType === FirstTimeFlowType.create,
- },
- });
history.push(DEFAULT_ROUTE);
}
};
From c1a4386a954fad0c78cc125dceeeb59936e6b7dc Mon Sep 17 00:00:00 2001
From: Harika <153644847+hjetpoluru@users.noreply.github.com>
Date: Tue, 17 Sep 2024 11:01:54 -0400
Subject: [PATCH 10/37] fix: Fixed flaky test for custom screen size (#27067)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
The fix for the flaky test is related to the custom screen size of the
window during execution.
The flaky test was identified in multiple test scenarios with a similar
pattern of false negatives in the automation tests. There were browser
errors that appeared after navigating and opening the devTools, with the
following error mentioned:
```
2024-08-22T20:14:57.507Z [driver] Called 'navigate' with arguments []
-----Received an error from Chrome-----
Request Storage.getStorageKeyForFrame failed. {"code":-32602,"message":"Frame tree node for given frame not found"}
Request Storage.getStorageKeyForFrame failed. {"code":-32602,"message":"Frame tree node for given frame not found"}
----------End of Chrome error----------
2024-08-22T20:15:04.239Z [driver] Called 'fill' with arguments ["#password","correct horse battery staple"]
```
And due to this error, the code mistakenly flags the test as failed and
attempts to capture a screenshot, leading to Due to this error, the code
mistakenly flags the test as failed and attempts to capture a
screenshot, leading to another false `error: NoSuchWindowError: no such
window: target window already closed.`
- The test specific to responive UI requires a specific window size
inorder to perform correctly and with help of @danjm suggestion I have
include the `constrainWindowSize: true` which meets the test criteria.
- Also I have noticed that the windows size is not required for the
`swap-send-test-utils.ts` and hence removed it.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27067?quickstart=1)
## **Related issues**
Fixes:
https://github.com/MetaMask/metamask-extension/issues/26898
https://github.com/MetaMask/metamask-extension/issues/26900
https://github.com/MetaMask/metamask-extension/issues/26637
https://github.com/MetaMask/metamask-extension/issues/26112
https://github.com/MetaMask/metamask-extension/issues/24624
## **Manual testing steps**
Run the below commands locally or in codespaces
Webpack build
yarn
yarn build:test:webpack
yarn build:test:webpack
ENABLE_MV3=false yarn test:e2e:single
test/e2e/tests/swap-send/swap-send-erc20.spec.ts --browser=chrome
ENABLE_MV3=false yarn test:e2e:single
test/e2e/tests/swap-send/swap-send-eth.spec.ts --browser=chrome
ENABLE_MV3=false yarn test:e2e:single
test/e2e/tests/account/metamask-responsive-ui.spec.js --browser=chrome
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
---
test/e2e/tests/account/metamask-responsive-ui.spec.js | 6 +++---
test/e2e/tests/swap-send/swap-send-test-utils.ts | 1 -
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/test/e2e/tests/account/metamask-responsive-ui.spec.js b/test/e2e/tests/account/metamask-responsive-ui.spec.js
index d9e9aa2f965c..037179b500b0 100644
--- a/test/e2e/tests/account/metamask-responsive-ui.spec.js
+++ b/test/e2e/tests/account/metamask-responsive-ui.spec.js
@@ -11,7 +11,7 @@ const FixtureBuilder = require('../../fixture-builder');
describe('MetaMask Responsive UI', function () {
it('Creating a new wallet @no-mmi', async function () {
- const driverOptions = { responsive: true };
+ const driverOptions = { constrainWindowSize: true };
await withFixtures(
{
@@ -81,7 +81,7 @@ describe('MetaMask Responsive UI', function () {
});
it('Importing existing wallet from lock page', async function () {
- const driverOptions = { responsive: true };
+ const driverOptions = { constrainWindowSize: true };
await withFixtures(
{
@@ -115,7 +115,7 @@ describe('MetaMask Responsive UI', function () {
});
it('Send Transaction from responsive window', async function () {
- const driverOptions = { responsive: true };
+ const driverOptions = { constrainWindowSize: true };
await withFixtures(
{
fixtures: new FixtureBuilder().build(),
diff --git a/test/e2e/tests/swap-send/swap-send-test-utils.ts b/test/e2e/tests/swap-send/swap-send-test-utils.ts
index c5f4d8bb3d9c..8eff9051b9d1 100644
--- a/test/e2e/tests/swap-send/swap-send-test-utils.ts
+++ b/test/e2e/tests/swap-send/swap-send-test-utils.ts
@@ -266,7 +266,6 @@ export const getSwapSendFixtures = (
) => {
const ETH_CONVERSION_RATE_USD = 3010;
return {
- driverOptions: { responsive: true },
fixtures: new FixtureBuilder()
.withPreferencesController({
featureFlags: {},
From bc4c4b1c2cf43d4e6667b82e80cf942a4e544f37 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Tavares?=
Date: Tue, 17 Sep 2024 17:20:16 +0100
Subject: [PATCH 11/37] chore: remove dead code (#27211)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
Removes unused code.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27211?quickstart=1)
## **Related issues**
Fixes: None
## **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/develop/.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/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
---
.../info/__snapshots__/info.test.tsx.snap | 114 ---------------
ui/components/app/confirm/info/index.ts | 1 -
ui/components/app/confirm/info/index.tsx | 1 -
.../app/confirm/info/info.stories.tsx | 51 -------
ui/components/app/confirm/info/info.test.tsx | 59 --------
ui/components/app/confirm/info/info.tsx | 131 ------------------
.../confirm/signature-message/index.ts | 1 -
.../signature-message/signature-message.tsx | 32 -----
8 files changed, 390 deletions(-)
delete mode 100644 ui/components/app/confirm/info/__snapshots__/info.test.tsx.snap
delete mode 100644 ui/components/app/confirm/info/index.ts
delete mode 100644 ui/components/app/confirm/info/index.tsx
delete mode 100644 ui/components/app/confirm/info/info.stories.tsx
delete mode 100644 ui/components/app/confirm/info/info.test.tsx
delete mode 100644 ui/components/app/confirm/info/info.tsx
delete mode 100644 ui/pages/confirmations/components/confirm/signature-message/index.ts
delete mode 100644 ui/pages/confirmations/components/confirm/signature-message/signature-message.tsx
diff --git a/ui/components/app/confirm/info/__snapshots__/info.test.tsx.snap b/ui/components/app/confirm/info/__snapshots__/info.test.tsx.snap
deleted file mode 100644
index 749964a79364..000000000000
--- a/ui/components/app/confirm/info/__snapshots__/info.test.tsx.snap
+++ /dev/null
@@ -1,114 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`ConfirmInfo should match snapshot 1`] = `
-
-
-
-
-
-
-
-
- 0xCcCCc...ccccC
-
-
-
-
-
-
-
-
-
- $834.32
-
-
- 0.05 ETH
-
-
-
-
-
-`;
diff --git a/ui/components/app/confirm/info/index.ts b/ui/components/app/confirm/info/index.ts
deleted file mode 100644
index e23e44f519bb..000000000000
--- a/ui/components/app/confirm/info/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { ConfirmInfo } from './info';
diff --git a/ui/components/app/confirm/info/index.tsx b/ui/components/app/confirm/info/index.tsx
deleted file mode 100644
index b247e432cc22..000000000000
--- a/ui/components/app/confirm/info/index.tsx
+++ /dev/null
@@ -1 +0,0 @@
-export * from './info';
diff --git a/ui/components/app/confirm/info/info.stories.tsx b/ui/components/app/confirm/info/info.stories.tsx
deleted file mode 100644
index d23726f39104..000000000000
--- a/ui/components/app/confirm/info/info.stories.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import React from 'react';
-import { ConfirmInfoRow } from './row';
-import { ConfirmInfo, ConfirmInfoRowConfig, ConfirmInfoRowType } from './info';
-
-const mockRowConfigs: ConfirmInfoRowConfig[] = [
- {
- label: 'Address',
- type: ConfirmInfoRowType.Address,
- rowProps: {
- address: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
- },
- },
- {
- type: ConfirmInfoRowType.Divider,
- },
- {
- label: 'Origin',
- type: ConfirmInfoRowType.UrlType,
- rowProps: {
- url: 'https://metamask.github.io',
- },
- },
- {
- label: 'Account',
- type: ConfirmInfoRowType.ValueDouble,
- rowProps: {
- left: '$834.32',
- right: '0.05 ETH',
- },
- },
-];
-
-const ConfirmInfoStory = {
- title: 'Components/App/Confirm/Info',
- component: ConfirmInfoRow,
-
- args: { rowConfigs: [...mockRowConfigs] },
- argTypes: {
- rowConfigs: {
- control: {
- type: 'object',
- },
- },
- },
-};
-
-export const DefaultStory = (args) => ;
-
-DefaultStory.storyName = 'Default';
-
-export default ConfirmInfoStory;
diff --git a/ui/components/app/confirm/info/info.test.tsx b/ui/components/app/confirm/info/info.test.tsx
deleted file mode 100644
index 113d964fd1f6..000000000000
--- a/ui/components/app/confirm/info/info.test.tsx
+++ /dev/null
@@ -1,59 +0,0 @@
-import React from 'react';
-import mockState from '../../../../../test/data/mock-state.json';
-import { renderWithProvider } from '../../../../../test/lib/render-helpers';
-import configureStore from '../../../../store/store';
-import { ConfirmInfo, ConfirmInfoRowConfig, ConfirmInfoRowType } from './info';
-
-const mockRowConfigs: ConfirmInfoRowConfig[] = [
- {
- label: 'Address',
- type: ConfirmInfoRowType.Address,
- rowProps: {
- address: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
- },
- },
- {
- type: ConfirmInfoRowType.Divider,
- },
- {
- label: 'Account',
- type: ConfirmInfoRowType.ValueDouble,
- rowProps: {
- left: '$834.32',
- right: '0.05 ETH',
- },
- },
-];
-
-describe('ConfirmInfo', () => {
- // TODO: Replace `any` with type
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const render = (storeOverrides: Record = {}) => {
- const store = configureStore({
- ...mockState.metamask,
- metamask: { ...mockState.metamask },
- ...storeOverrides,
- });
-
- return renderWithProvider(
- ,
- store,
- );
- };
-
- it('should match snapshot', () => {
- const { container } = render(mockRowConfigs);
- expect(container).toMatchSnapshot();
- });
-
- it('renders the correct number of rows provided', () => {
- const { container } = render(mockRowConfigs);
- const numOfDividers = mockRowConfigs.filter(
- (rowConfig) => rowConfig.type === ConfirmInfoRowType.Divider,
- ).length;
-
- expect(container.querySelectorAll('.confirm-info-row')).toHaveLength(
- mockRowConfigs.length - numOfDividers,
- );
- });
-});
diff --git a/ui/components/app/confirm/info/info.tsx b/ui/components/app/confirm/info/info.tsx
deleted file mode 100644
index 9edd0a22ec49..000000000000
--- a/ui/components/app/confirm/info/info.tsx
+++ /dev/null
@@ -1,131 +0,0 @@
-import React from 'react';
-
-import { captureException } from '@sentry/browser';
-
-import {
- BackgroundColor,
- BorderRadius,
- Display,
- FlexDirection,
-} from '../../../../helpers/constants/design-system';
-import { Box } from '../../../component-library';
-import {
- ConfirmInfoRow,
- ConfirmInfoRowAddress,
- ConfirmInfoRowAddressProps,
- ConfirmInfoRowDivider,
- ConfirmInfoRowProps,
- ConfirmInfoRowText,
- ConfirmInfoRowTextProps,
- ConfirmInfoRowUrl,
- ConfirmInfoRowUrlProps,
- ConfirmInfoRowValueDouble,
- ConfirmInfoRowValueDoubleProps,
- ConfirmInfoRowVariant,
-} from './row';
-
-export enum ConfirmInfoRowType {
- Address = 'address',
- Divider = 'divider',
- Text = 'text',
- UrlType = 'url',
- ValueDouble = 'value-double',
-}
-
-type ConfirmInfoTypeProps =
- | ConfirmInfoRowAddressProps
- | ConfirmInfoRowTextProps
- | ConfirmInfoRowUrlProps
- | ConfirmInfoRowValueDoubleProps;
-
-// TODO: Replace `any` with type
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-const TYPE_TO_COMPONENT: Record = {
- [ConfirmInfoRowType.Address]: ({ address }: ConfirmInfoRowAddressProps) => {
- return ;
- },
- [ConfirmInfoRowType.Divider]: () => {
- return ;
- },
- [ConfirmInfoRowType.Text]: ({ text }: ConfirmInfoRowTextProps) => {
- return ;
- },
- [ConfirmInfoRowType.UrlType]: ({ url }: ConfirmInfoRowUrlProps) => {
- return ;
- },
- [ConfirmInfoRowType.ValueDouble]: ({
- left,
- right,
- }: ConfirmInfoRowValueDoubleProps) => {
- return ;
- },
-};
-
-export type ConfirmInfoRowConfig = {
- /** The display label text. This should be required unless it is a 'divider' variant */
- label?: ConfirmInfoRowProps['label'];
-
- /** Optional, and likely needed, props passed to the row */
- rowProps?: ConfirmInfoTypeProps;
-
- /** The type of the row e.g. address, divider, value-double */
- type: ConfirmInfoRowType;
-
- /** Optional row variant */
- variant?: ConfirmInfoRowVariant;
-};
-
-type ConfirmInfoProps = {
- rowConfigs: ConfirmInfoRowConfig[];
-};
-
-/**
- * ConfirmInfo receives a custom config object and displays a list of ConfirmInfoRow components
- *
- * @param options
- * @param options.rowConfigs
- */
-export const ConfirmInfo: React.FC = ({
- rowConfigs = [],
-}) => (
-
- {rowConfigs.map((rowConfig: ConfirmInfoRowConfig, index) => {
- const { label, rowProps, type, variant } = rowConfig;
- const component = TYPE_TO_COMPONENT[type];
-
- if (!component) {
- const error = new Error(`ConfirmInfo: Unknown row type: ${type}`);
- console.error(error);
- captureException(error);
- return null;
- }
-
- if (type === ConfirmInfoRowType.Divider) {
- const key = `confirm-info-divider-${rowConfigs
- .map(({ label: _label }) => _label)
- .concat('-')}-${index}`;
-
- return (
-
-
-
- );
- }
-
- const key = `confirm-info-row-${label}-${index}`;
-
- return (
-
-
- {component(rowProps)}
-
-
- );
- })}
-
-);
diff --git a/ui/pages/confirmations/components/confirm/signature-message/index.ts b/ui/pages/confirmations/components/confirm/signature-message/index.ts
deleted file mode 100644
index e95d7f64485a..000000000000
--- a/ui/pages/confirmations/components/confirm/signature-message/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default as SignatureMessage } from './signature-message';
diff --git a/ui/pages/confirmations/components/confirm/signature-message/signature-message.tsx b/ui/pages/confirmations/components/confirm/signature-message/signature-message.tsx
deleted file mode 100644
index a9741d41c1f7..000000000000
--- a/ui/pages/confirmations/components/confirm/signature-message/signature-message.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import React, { memo } from 'react';
-
-import { hexToText } from '../../../../../helpers/utils/util';
-import { useI18nContext } from '../../../../../hooks/useI18nContext';
-import {
- ConfirmInfoRow,
- ConfirmInfoRowText,
-} from '../../../../../components/app/confirm/info/row';
-import { SignatureRequestType } from '../../../types/confirm';
-import { ConfirmInfoSection } from '../../../../../components/app/confirm/info/row/section';
-import { useConfirmContext } from '../../../context/confirm';
-
-const SignatureMessage: React.FC = memo(() => {
- const t = useI18nContext();
- const { currentConfirmation } = useConfirmContext();
-
- if (!currentConfirmation?.msgParams?.data) {
- return null;
- }
-
- return (
-
-
-
-
-
- );
-});
-
-export default SignatureMessage;
From c462fb89958593cff2f2748ebbcab12774aa8e43 Mon Sep 17 00:00:00 2001
From: Prithpal Sooriya
Date: Tue, 17 Sep 2024 20:17:38 +0100
Subject: [PATCH 12/37] feat: upgrade notification controllers (#27224)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
Bumps:
- `@metamask/profile-sync-controller` from `^0.7.0` to `^0.8.0`
- `@metamask/notification-services-controller` from `^0.6.0` to `^0.7.0`
This fixes a critical issue where we were not using the same UserStorage
hashed entry. See release library changelog
https://github.com/MetaMask/core/blob/main/packages/profile-sync-controller/CHANGELOG.md#fixed
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27224?quickstart=1)
## **Related issues**
Fixes: https://consensyssoftware.atlassian.net/browse/NOTIFY-1118
## **Manual testing steps**
Test notifications flow:
- Enable/Disable Notifications
## **Screenshots/Recordings**
### **Before**
### **After**
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.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/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
---
package.json | 4 ++--
yarn.lock | 54 ++++++++++++++++++++++++++--------------------------
2 files changed, 29 insertions(+), 29 deletions(-)
diff --git a/package.json b/package.json
index b3b5b22f7e86..70195f5ae650 100644
--- a/package.json
+++ b/package.json
@@ -336,7 +336,7 @@
"@metamask/name-controller": "^8.0.0",
"@metamask/network-controller": "patch:@metamask/network-controller@npm%3A20.2.0#~/.yarn/patches/@metamask-network-controller-npm-20.2.0-98b1a5ae59.patch",
"@metamask/notification-controller": "^6.0.0",
- "@metamask/notification-services-controller": "^0.5.0",
+ "@metamask/notification-services-controller": "^0.7.0",
"@metamask/object-multiplex": "^2.0.0",
"@metamask/obs-store": "^9.0.0",
"@metamask/permission-controller": "^10.0.0",
@@ -344,7 +344,7 @@
"@metamask/phishing-controller": "^12.0.1",
"@metamask/post-message-stream": "^8.0.0",
"@metamask/ppom-validator": "0.34.0",
- "@metamask/profile-sync-controller": "^0.5.0",
+ "@metamask/profile-sync-controller": "^0.8.0",
"@metamask/providers": "^14.0.2",
"@metamask/queued-request-controller": "^2.0.0",
"@metamask/rate-limit-controller": "^6.0.0",
diff --git a/yarn.lock b/yarn.lock
index e6bf174ada48..2149a6bd2404 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5784,21 +5784,21 @@ __metadata:
languageName: node
linkType: hard
-"@metamask/notification-services-controller@npm:^0.5.0":
- version: 0.5.0
- resolution: "@metamask/notification-services-controller@npm:0.5.0"
+"@metamask/notification-services-controller@npm:^0.7.0":
+ version: 0.7.0
+ resolution: "@metamask/notification-services-controller@npm:0.7.0"
dependencies:
"@contentful/rich-text-html-renderer": "npm:^16.5.2"
- "@metamask/base-controller": "npm:^7.0.0"
- "@metamask/controller-utils": "npm:^11.2.0"
+ "@metamask/base-controller": "npm:^7.0.1"
+ "@metamask/controller-utils": "npm:^11.3.0"
bignumber.js: "npm:^4.1.0"
firebase: "npm:^10.11.0"
loglevel: "npm:^1.8.1"
uuid: "npm:^8.3.2"
peerDependencies:
"@metamask/keyring-controller": ^17.0.0
- "@metamask/profile-sync-controller": ^0.5.0
- checksum: 10/e945cbf0b7138d22f1078844575dc89c990ddc6669724d1ce0db5ad43c74a86da1c5e1ab12614afbcc5c49125b09365689de2a2c9548af426932f4c1397a66bd
+ "@metamask/profile-sync-controller": ^0.0.0
+ checksum: 10/1fc72086686aeef4c72d9eb7726d086a147a4079c178a6de23269fa39a3d861c54fe6dfe79bd9b5c8bf9afa278371408092bd37f3e8f814e65c7aca3573655f5
languageName: node
linkType: hard
@@ -6010,13 +6010,13 @@ __metadata:
languageName: node
linkType: hard
-"@metamask/profile-sync-controller@npm:^0.5.0":
- version: 0.5.0
- resolution: "@metamask/profile-sync-controller@npm:0.5.0"
+"@metamask/profile-sync-controller@npm:^0.8.0":
+ version: 0.8.0
+ resolution: "@metamask/profile-sync-controller@npm:0.8.0"
dependencies:
- "@metamask/base-controller": "npm:^7.0.0"
- "@metamask/snaps-sdk": "npm:^6.1.1"
- "@metamask/snaps-utils": "npm:^7.8.1"
+ "@metamask/base-controller": "npm:^7.0.1"
+ "@metamask/snaps-sdk": "npm:^6.5.0"
+ "@metamask/snaps-utils": "npm:^8.1.1"
"@noble/ciphers": "npm:^0.5.2"
"@noble/hashes": "npm:^1.4.0"
immer: "npm:^9.0.6"
@@ -6025,8 +6025,8 @@ __metadata:
peerDependencies:
"@metamask/accounts-controller": ^18.1.1
"@metamask/keyring-controller": ^17.2.0
- "@metamask/snaps-controllers": ^9.3.0
- checksum: 10/96a31ca2692af85100bd690aa290d6c954378aa14be0dd507afda46c37d761c5e398da4e93ed0f6f7f97267a82def7f4b12b45805cd7673381a6404f810511ff
+ "@metamask/snaps-controllers": ^9.7.0
+ checksum: 10/613e2e87615f1db4a1a4559895a74c2b89c15720e831440eec0916aa96305f3db9b3e0926ac4a5d7532c462baaa18a117e2b9aa107949777163488c203cfea05
languageName: node
linkType: hard
@@ -6389,9 +6389,9 @@ __metadata:
languageName: node
linkType: hard
-"@metamask/snaps-utils@npm:^8.0.0, @metamask/snaps-utils@npm:^8.0.1":
- version: 8.0.1
- resolution: "@metamask/snaps-utils@npm:8.0.1"
+"@metamask/snaps-utils@npm:^8.0.0, @metamask/snaps-utils@npm:^8.0.1, @metamask/snaps-utils@npm:^8.1.1":
+ version: 8.1.1
+ resolution: "@metamask/snaps-utils@npm:8.1.1"
dependencies:
"@babel/core": "npm:^7.23.2"
"@babel/types": "npm:^7.23.0"
@@ -6401,9 +6401,9 @@ __metadata:
"@metamask/rpc-errors": "npm:^6.3.1"
"@metamask/slip44": "npm:^4.0.0"
"@metamask/snaps-registry": "npm:^3.2.1"
- "@metamask/snaps-sdk": "npm:^6.2.1"
+ "@metamask/snaps-sdk": "npm:^6.5.0"
"@metamask/superstruct": "npm:^3.1.0"
- "@metamask/utils": "npm:^9.1.0"
+ "@metamask/utils": "npm:^9.2.1"
"@noble/hashes": "npm:^1.3.1"
"@scure/base": "npm:^1.1.1"
chalk: "npm:^4.1.2"
@@ -6416,7 +6416,7 @@ __metadata:
semver: "npm:^7.5.4"
ses: "npm:^1.1.0"
validate-npm-package-name: "npm:^5.0.0"
- checksum: 10/4c0d58ad04f1e4c625dd01aaf171de0f538afc2003ac928159deee5ebed6d490ccd50575ad585b4f6846aa8d00bccd8f1ea4b32f124e6427873fb985cae8513f
+ checksum: 10/f4ceb52a1f9578993c88c82a67f4f041309af51c83ff5caa3fed080f36b54d14ea7da807ce1cf19a13600dd0e77c51af70398e8c7bb78f0ba99a037f4d22610f
languageName: node
linkType: hard
@@ -6581,9 +6581,9 @@ __metadata:
languageName: node
linkType: hard
-"@metamask/utils@npm:^9.0.0, @metamask/utils@npm:^9.1.0":
- version: 9.1.0
- resolution: "@metamask/utils@npm:9.1.0"
+"@metamask/utils@npm:^9.0.0, @metamask/utils@npm:^9.1.0, @metamask/utils@npm:^9.2.1":
+ version: 9.2.1
+ resolution: "@metamask/utils@npm:9.2.1"
dependencies:
"@ethereumjs/tx": "npm:^4.2.0"
"@metamask/superstruct": "npm:^3.1.0"
@@ -6594,7 +6594,7 @@ __metadata:
pony-cause: "npm:^2.1.10"
semver: "npm:^7.5.4"
uuid: "npm:^9.0.1"
- checksum: 10/7335e151a51be92e86868dc48b3ee78c376d4edd5d758d334176027247637ab22839d8f663bd02542c0a19b05ecec456bedab5f36436689cf3d953ca36d91781
+ checksum: 10/2192797afd91af19898e107afeaf63e89b61dc7285e0a75d0cc814b5b288e4cdfc856781b01904034c4d2c1efd9bdab512af24c7e4dfe7b77a03f1f3d9dec7e8
languageName: node
linkType: hard
@@ -26036,7 +26036,7 @@ __metadata:
"@metamask/name-controller": "npm:^8.0.0"
"@metamask/network-controller": "patch:@metamask/network-controller@npm%3A20.2.0#~/.yarn/patches/@metamask-network-controller-npm-20.2.0-98b1a5ae59.patch"
"@metamask/notification-controller": "npm:^6.0.0"
- "@metamask/notification-services-controller": "npm:^0.5.0"
+ "@metamask/notification-services-controller": "npm:^0.7.0"
"@metamask/object-multiplex": "npm:^2.0.0"
"@metamask/obs-store": "npm:^9.0.0"
"@metamask/permission-controller": "npm:^10.0.0"
@@ -26045,7 +26045,7 @@ __metadata:
"@metamask/phishing-warning": "npm:^4.0.0"
"@metamask/post-message-stream": "npm:^8.0.0"
"@metamask/ppom-validator": "npm:0.34.0"
- "@metamask/profile-sync-controller": "npm:^0.5.0"
+ "@metamask/profile-sync-controller": "npm:^0.8.0"
"@metamask/providers": "npm:^14.0.2"
"@metamask/queued-request-controller": "npm:^2.0.0"
"@metamask/rate-limit-controller": "npm:^6.0.0"
From bc7929b1c96f09e5ae3c3b76d4ef2c649b0dd78a Mon Sep 17 00:00:00 2001
From: Nick Gambino <35090461+gambinish@users.noreply.github.com>
Date: Tue, 17 Sep 2024 15:09:17 -0700
Subject: [PATCH 13/37] chore: Add currency conversion telemetry (#26876)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
In order to figure out which currencies we should support 24hr % change,
we need to know which currencies are the most popular.
Adds currency change dropdown event to telemetry events.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/26876?quickstart=1)
## **Related issues**
Fixes: https://consensyssoftware.atlassian.net/browse/MMASSETS-344
## **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/develop/.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/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
---
app/scripts/controllers/metametrics.js | 1 +
shared/constants/metametrics.ts | 5 +++++
.../settings/settings-tab/settings-tab.component.js | 11 ++++++++++-
3 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/app/scripts/controllers/metametrics.js b/app/scripts/controllers/metametrics.js
index d815607d27e8..d799249bb71b 100644
--- a/app/scripts/controllers/metametrics.js
+++ b/app/scripts/controllers/metametrics.js
@@ -837,6 +837,7 @@ export default class MetaMetricsController {
metamaskState.useTokenDetection,
[MetaMetricsUserTrait.UseNativeCurrencyAsPrimaryCurrency]:
metamaskState.useNativeCurrencyAsPrimaryCurrency,
+ [MetaMetricsUserTrait.CurrentCurrency]: metamaskState.currentCurrency,
///: BEGIN:ONLY_INCLUDE_IF(build-mmi)
[MetaMetricsUserTrait.MmiExtensionId]: this.extension?.runtime?.id,
[MetaMetricsUserTrait.MmiAccountAddress]: mmiAccountAddress,
diff --git a/shared/constants/metametrics.ts b/shared/constants/metametrics.ts
index daec305bfb11..0ad1bc9e1deb 100644
--- a/shared/constants/metametrics.ts
+++ b/shared/constants/metametrics.ts
@@ -468,6 +468,10 @@ export enum MetaMetricsUserTrait {
MmiIsCustodian = 'mmi_is_custodian',
///: END:ONLY_INCLUDE_IF
PetnameAddressCount = 'petname_addresses_count',
+ /**
+ * Identified when the user selects a currency from settings
+ */
+ CurrentCurrency = 'current_currency',
}
/**
@@ -514,6 +518,7 @@ export enum MetaMetricsEventName {
BridgeLinkClicked = 'Bridge Link Clicked',
BitcoinSupportToggled = 'Bitcoin Support Toggled',
BitcoinTestnetSupportToggled = 'Bitcoin Testnet Support Toggled',
+ CurrentCurrency = 'Current Currency',
DappViewed = 'Dapp Viewed',
DecryptionApproved = 'Decryption Approved',
DecryptionRejected = 'Decryption Rejected',
diff --git a/ui/pages/settings/settings-tab/settings-tab.component.js b/ui/pages/settings/settings-tab/settings-tab.component.js
index 45407ece008d..d798b62f77ba 100644
--- a/ui/pages/settings/settings-tab/settings-tab.component.js
+++ b/ui/pages/settings/settings-tab/settings-tab.component.js
@@ -119,7 +119,16 @@ export default class SettingsTab extends PureComponent {
id="select-currency"
options={currencyOptions}
selectedOption={currentCurrency}
- onChange={(newCurrency) => setCurrentCurrency(newCurrency)}
+ onChange={(newCurrency) => {
+ setCurrentCurrency(newCurrency);
+ this.context.trackEvent({
+ category: MetaMetricsEventCategory.Settings,
+ event: MetaMetricsEventName.CurrentCurrency,
+ properties: {
+ current_currency: newCurrency,
+ },
+ });
+ }}
/>
From eadc7075731ad95662b9a4f07b0cddd0328d9695 Mon Sep 17 00:00:00 2001
From: Matteo Scurati
Date: Wed, 18 Sep 2024 08:37:17 +0200
Subject: [PATCH 14/37] fix: :pencil2: fix event property typo (#27228)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
This PR fixes a typo for a property used by the event emitted by the
toggle to turn basic functionality on or off.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27228?quickstart=1)
## **Related issues**
N/A
## **Manual testing steps**
N/A
## **Screenshots/Recordings**
N/A
### **Before**
N/A
### **After**
N/A
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.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/develop/.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.
---
.../basic-configuration-modal/basic-configuration-modal.tsx | 2 +-
ui/pages/onboarding-flow/privacy-settings/privacy-settings.js | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/ui/components/app/basic-configuration-modal/basic-configuration-modal.tsx b/ui/components/app/basic-configuration-modal/basic-configuration-modal.tsx
index d9699c9ebc8a..a6b083eccc16 100644
--- a/ui/components/app/basic-configuration-modal/basic-configuration-modal.tsx
+++ b/ui/components/app/basic-configuration-modal/basic-configuration-modal.tsx
@@ -150,7 +150,7 @@ export function BasicConfigurationModal() {
category: MetaMetricsEventCategory.Onboarding,
event: MetaMetricsEventName.SettingsUpdated,
properties: {
- settings_group: 'advanced',
+ settings_group: 'onboarding_advanced_configuration',
settings_type: 'basic_functionality',
old_value: true,
new_value: false,
diff --git a/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js b/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js
index 3012fe9808f2..9f1bb0dcf8c3 100644
--- a/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js
+++ b/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js
@@ -277,10 +277,11 @@ export default function PrivacySettings() {
category: MetaMetricsEventCategory.Onboarding,
event: MetaMetricsEventName.SettingsUpdated,
properties: {
- settings_group: 'advanced',
+ settings_group: 'onboarding_advanced_configuration',
settings_type: 'basic_functionality',
old_value: false,
new_value: true,
+ was_profile_syncing_on: false,
},
});
}
From 8d3e6ad21258bd98fe72fe0b78972352f7b1cc41 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Tavares?=
Date: Wed, 18 Sep 2024 10:48:43 +0100
Subject: [PATCH 15/37] fix: UI transaction integration tests (#27130)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
* Fixes warnings to redesigned transactions existing UI integration
tests.
* Adds new UI integration tests to erc20 approve confirmation.
** Some of those tests required interaction with tooltips, so added a
way to automatically include a tooltip data-testid whenever the Confirm
row has a data-testid set (in case there is a tooltip obviously).
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27130?quickstart=1)
## **Related issues**
Fixes: None
## **Screenshots/Recordings**
No visual changes. This is PR mainly adds/updates tests.
## **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/develop/.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/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
---
shared/lib/four-byte.ts | 1 -
.../confirmations/signatures/permit.test.tsx | 4 +-
.../signatures/personalSign.test.tsx | 4 +-
.../transactions/alerts.test.tsx | 148 +++++----
.../contract-interaction.test.tsx | 125 +++++---
.../transactions/erc20-approve.test.tsx | 300 +++++++++++++++---
.../transactions/erc721-approve.test.tsx | 63 ++--
.../transactions/transactionDataHelpers.tsx | 2 +-
.../data/integration-init-state.json | 94 +++---
test/integration/helpers.tsx | 4 +-
ui/components/app/confirm/info/row/row.tsx | 3 +
.../__snapshots__/approve.test.tsx.snap | 12 +
.../approve-details.test.tsx.snap | 1 +
.../approve-details/approve-details.tsx | 8 +-
.../__snapshots__/spending-cap.test.tsx.snap | 3 +
.../approve/spending-cap/spending-cap.tsx | 3 +-
.../base-transaction-info.test.tsx.snap | 9 +
.../edit-gas-fees-row.test.tsx.snap | 1 +
.../gas-fees-details.test.tsx.snap | 1 +
.../gas-fees-section.test.tsx.snap | 1 +
.../transaction-data.test.tsx.snap | 38 +++
.../transaction-details.test.tsx.snap | 2 +
22 files changed, 596 insertions(+), 231 deletions(-)
diff --git a/shared/lib/four-byte.ts b/shared/lib/four-byte.ts
index 167dfc563b73..c8d67af7b1f4 100644
--- a/shared/lib/four-byte.ts
+++ b/shared/lib/four-byte.ts
@@ -57,7 +57,6 @@ export async function getMethodDataAsync(
console.error(e);
return null;
});
- console.log('fourByteSig = ', fourByteSig);
}
if (!registry) {
diff --git a/test/integration/confirmations/signatures/permit.test.tsx b/test/integration/confirmations/signatures/permit.test.tsx
index 3670b654502d..809ac988962f 100644
--- a/test/integration/confirmations/signatures/permit.test.tsx
+++ b/test/integration/confirmations/signatures/permit.test.tsx
@@ -105,7 +105,7 @@ describe('Permit Confirmation', () => {
accountName,
);
expect(screen.getByTestId('header-network-display-name')).toHaveTextContent(
- 'Chain 5',
+ 'Sepolia',
);
fireEvent.click(screen.getByTestId('header-info__account-details-button'));
@@ -120,7 +120,7 @@ describe('Permit Confirmation', () => {
);
expect(
screen.getByTestId('confirmation-account-details-modal__account-balance'),
- ).toHaveTextContent('1.58271596ETH');
+ ).toHaveTextContent('1.582717SepoliaETH');
let confirmAccountDetailsModalMetricsEvent;
diff --git a/test/integration/confirmations/signatures/personalSign.test.tsx b/test/integration/confirmations/signatures/personalSign.test.tsx
index 528655924dbe..9737a3e30ad9 100644
--- a/test/integration/confirmations/signatures/personalSign.test.tsx
+++ b/test/integration/confirmations/signatures/personalSign.test.tsx
@@ -87,7 +87,7 @@ describe('PersonalSign Confirmation', () => {
expect(getByTestId('header-account-name')).toHaveTextContent(accountName);
expect(getByTestId('header-network-display-name')).toHaveTextContent(
- 'Chain 5',
+ 'Sepolia',
);
fireEvent.click(getByTestId('header-info__account-details-button'));
@@ -106,7 +106,7 @@ describe('PersonalSign Confirmation', () => {
);
expect(
getByTestId('confirmation-account-details-modal__account-balance'),
- ).toHaveTextContent('1.58271596ETH');
+ ).toHaveTextContent('1.582717SepoliaETH');
let confirmAccountDetailsModalMetricsEvent;
diff --git a/test/integration/confirmations/transactions/alerts.test.tsx b/test/integration/confirmations/transactions/alerts.test.tsx
index 1e07ddcdd68d..74d37c858b0f 100644
--- a/test/integration/confirmations/transactions/alerts.test.tsx
+++ b/test/integration/confirmations/transactions/alerts.test.tsx
@@ -6,6 +6,7 @@ import mockMetaMaskState from '../../data/integration-init-state.json';
import { integrationTestRender } from '../../../lib/render-helpers';
import * as backgroundConnection from '../../../../ui/store/background-connection';
import { createMockImplementation, mock4byte } from '../../helpers';
+import { createTestProviderTools } from '../../../stub/provider';
import { getUnapprovedApproveTransaction } from './transactionDataHelpers';
jest.mock('../../../../ui/store/background-connection', () => ({
@@ -75,7 +76,17 @@ const setupSubmitRequestToBackgroundMocks = (
);
};
-describe('Contract Interaction Confirmation', () => {
+describe('Contract Interaction Confirmation Alerts', () => {
+ beforeAll(() => {
+ const { provider } = createTestProviderTools({
+ networkId: 'sepolia',
+ chainId: '0xaa36a7',
+ });
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ global.ethereumProvider = provider as any;
+ });
+
beforeEach(() => {
jest.resetAllMocks();
setupSubmitRequestToBackgroundMocks();
@@ -87,6 +98,11 @@ describe('Contract Interaction Confirmation', () => {
nock.cleanAll();
});
+ afterAll(() => {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ delete (global as any).ethereumProvider;
+ });
+
it('displays the alert when network is busy', async () => {
const account =
mockMetaMaskState.internalAccounts.accounts[
@@ -97,12 +113,12 @@ describe('Contract Interaction Confirmation', () => {
const mockedMetaMaskState =
getMetaMaskStateWithUnapprovedApproveTransaction(account.address);
- const { findByTestId, getByTestId, queryByTestId } =
+ await act(async () => {
await integrationTestRender({
preloadedState: {
...mockedMetaMaskState,
gasFeeEstimatesByChainId: {
- '0x5': {
+ '0xaa36a7': {
gasFeeEstimates: {
networkCongestion: 1.0005,
},
@@ -111,29 +127,28 @@ describe('Contract Interaction Confirmation', () => {
},
backgroundConnection: backgroundConnectionMocked,
});
-
- act(() => {
- fireEvent.click(getByTestId('inline-alert'));
});
- expect(await findByTestId('alert-modal')).toBeInTheDocument();
+ fireEvent.click(screen.getByTestId('inline-alert'));
+
+ expect(await screen.findByTestId('alert-modal')).toBeInTheDocument();
expect(
- await findByTestId('alert-modal__selected-alert'),
+ await screen.findByTestId('alert-modal__selected-alert'),
).toBeInTheDocument();
- expect(await findByTestId('alert-modal__selected-alert')).toHaveTextContent(
- 'Gas prices are high and estimates are less accurate.',
- );
+ expect(
+ await screen.findByTestId('alert-modal__selected-alert'),
+ ).toHaveTextContent('Gas prices are high and estimates are less accurate.');
- expect(await findByTestId('alert-modal-button')).toBeInTheDocument();
- const alertModalConfirmButton = await findByTestId('alert-modal-button');
+ expect(await screen.findByTestId('alert-modal-button')).toBeInTheDocument();
+ const alertModalConfirmButton = await screen.findByTestId(
+ 'alert-modal-button',
+ );
- act(() => {
- fireEvent.click(alertModalConfirmButton);
- });
+ fireEvent.click(alertModalConfirmButton);
- expect(queryByTestId('alert-modal')).not.toBeInTheDocument();
+ expect(screen.queryByTestId('alert-modal')).not.toBeInTheDocument();
});
it('displays the alert when gas estimate fails', async () => {
@@ -157,7 +172,7 @@ describe('Contract Interaction Confirmation', () => {
},
};
- const { findByTestId, getByTestId, queryByTestId } =
+ await act(async () => {
await integrationTestRender({
preloadedState: {
...mockedMetaMaskState,
@@ -165,29 +180,30 @@ describe('Contract Interaction Confirmation', () => {
},
backgroundConnection: backgroundConnectionMocked,
});
-
- act(() => {
- fireEvent.click(getByTestId('inline-alert'));
});
- expect(await findByTestId('alert-modal')).toBeInTheDocument();
+ fireEvent.click(screen.getByTestId('inline-alert'));
+
+ expect(await screen.findByTestId('alert-modal')).toBeInTheDocument();
expect(
- await findByTestId('alert-modal__selected-alert'),
+ await screen.findByTestId('alert-modal__selected-alert'),
).toBeInTheDocument();
- expect(await findByTestId('alert-modal__selected-alert')).toHaveTextContent(
+ expect(
+ await screen.findByTestId('alert-modal__selected-alert'),
+ ).toHaveTextContent(
'We’re unable to provide an accurate fee and this estimate might be high. We suggest you to input a custom gas limit, but there’s a risk the transaction will still fail.',
);
- expect(await findByTestId('alert-modal-button')).toBeInTheDocument();
- const alertModalConfirmButton = await findByTestId('alert-modal-button');
+ expect(await screen.findByTestId('alert-modal-button')).toBeInTheDocument();
+ const alertModalConfirmButton = await screen.findByTestId(
+ 'alert-modal-button',
+ );
- act(() => {
- fireEvent.click(alertModalConfirmButton);
- });
+ fireEvent.click(alertModalConfirmButton);
- expect(queryByTestId('alert-modal')).not.toBeInTheDocument();
+ expect(screen.queryByTestId('alert-modal')).not.toBeInTheDocument();
});
it('displays the alert for insufficient gas', async () => {
@@ -202,33 +218,35 @@ describe('Contract Interaction Confirmation', () => {
const transaction = mockedMetaMaskState.transactions[0];
transaction.txParams.gas = '0x0';
- const { findByTestId, getByTestId } = await integrationTestRender({
- preloadedState: {
- ...mockedMetaMaskState,
- transactions: [transaction],
- },
- backgroundConnection: backgroundConnectionMocked,
+ await act(async () => {
+ await integrationTestRender({
+ preloadedState: {
+ ...mockedMetaMaskState,
+ transactions: [transaction],
+ },
+ backgroundConnection: backgroundConnectionMocked,
+ });
});
- act(() => {
- fireEvent.click(getByTestId('inline-alert'));
- });
+ fireEvent.click(screen.getByTestId('inline-alert'));
- expect(await findByTestId('alert-modal')).toBeInTheDocument();
+ expect(await screen.findByTestId('alert-modal')).toBeInTheDocument();
expect(
- await findByTestId('alert-modal__selected-alert'),
+ await screen.findByTestId('alert-modal__selected-alert'),
).toBeInTheDocument();
- expect(await findByTestId('alert-modal__selected-alert')).toHaveTextContent(
+ expect(
+ await screen.findByTestId('alert-modal__selected-alert'),
+ ).toHaveTextContent(
'To continue with this transaction, you’ll need to increase the gas limit to 21000 or higher.',
);
expect(
- await findByTestId('alert-modal-action-showAdvancedGasModal'),
+ await screen.findByTestId('alert-modal-action-showAdvancedGasModal'),
).toBeInTheDocument();
expect(
- await findByTestId('alert-modal-action-showAdvancedGasModal'),
+ await screen.findByTestId('alert-modal-action-showAdvancedGasModal'),
).toHaveTextContent('Update gas limit');
});
@@ -245,34 +263,36 @@ describe('Contract Interaction Confirmation', () => {
const transaction = mockedMetaMaskState.transactions[0];
transaction.gasFeeEstimates.type = 'none';
- const { findByTestId, getByTestId } = await integrationTestRender({
- preloadedState: {
- ...mockedMetaMaskState,
- gasEstimateType: 'none',
- transactions: [transaction],
- },
- backgroundConnection: backgroundConnectionMocked,
+ await act(async () => {
+ await integrationTestRender({
+ preloadedState: {
+ ...mockedMetaMaskState,
+ gasEstimateType: 'none',
+ transactions: [transaction],
+ },
+ backgroundConnection: backgroundConnectionMocked,
+ });
});
- act(() => {
- fireEvent.click(getByTestId('inline-alert'));
- });
+ fireEvent.click(screen.getByTestId('inline-alert'));
- expect(await findByTestId('alert-modal')).toBeInTheDocument();
+ expect(await screen.findByTestId('alert-modal')).toBeInTheDocument();
expect(
- await findByTestId('alert-modal__selected-alert'),
+ await screen.findByTestId('alert-modal__selected-alert'),
).toBeInTheDocument();
- expect(await findByTestId('alert-modal__selected-alert')).toHaveTextContent(
+ expect(
+ await screen.findByTestId('alert-modal__selected-alert'),
+ ).toHaveTextContent(
'We can’t move forward with this transaction until you manually update the fee.',
);
expect(
- await findByTestId('alert-modal-action-showAdvancedGasModal'),
+ await screen.findByTestId('alert-modal-action-showAdvancedGasModal'),
).toBeInTheDocument();
expect(
- await findByTestId('alert-modal-action-showAdvancedGasModal'),
+ await screen.findByTestId('alert-modal-action-showAdvancedGasModal'),
).toHaveTextContent('Update fee');
});
@@ -331,9 +351,7 @@ describe('Contract Interaction Confirmation', () => {
expect(await screen.getByTestId('inline-alert')).toBeInTheDocument();
- act(() => {
- fireEvent.click(screen.getByTestId('inline-alert'));
- });
+ fireEvent.click(screen.getByTestId('inline-alert'));
expect(await screen.findByTestId('alert-modal')).toBeInTheDocument();
@@ -348,7 +366,7 @@ describe('Contract Interaction Confirmation', () => {
);
});
- it('displays the alert for gas fees too', async () => {
+ it('displays the alert for gas fees too low', async () => {
const account =
mockMetaMaskState.internalAccounts.accounts[
mockMetaMaskState.internalAccounts
@@ -372,9 +390,7 @@ describe('Contract Interaction Confirmation', () => {
});
});
- act(() => {
- fireEvent.click(screen.getByTestId('inline-alert'));
- });
+ fireEvent.click(screen.getByTestId('inline-alert'));
expect(await screen.findByTestId('alert-modal')).toBeInTheDocument();
diff --git a/test/integration/confirmations/transactions/contract-interaction.test.tsx b/test/integration/confirmations/transactions/contract-interaction.test.tsx
index 7d07dc31e7db..cea1ed6f54bc 100644
--- a/test/integration/confirmations/transactions/contract-interaction.test.tsx
+++ b/test/integration/confirmations/transactions/contract-interaction.test.tsx
@@ -1,4 +1,10 @@
-import { fireEvent, waitFor, within } from '@testing-library/react';
+import {
+ fireEvent,
+ waitFor,
+ within,
+ screen,
+ act,
+} from '@testing-library/react';
import { ApprovalType } from '@metamask/controller-utils';
import nock from 'nock';
import { TransactionType } from '@metamask/transaction-controller';
@@ -46,12 +52,12 @@ const getMetaMaskStateWithUnapprovedContractInteraction = ({
},
nextNonce: '8',
currencyRates: {
- ETH: {
+ SepoliaETH: {
conversionDate: 1721392020.645,
conversionRate: 3404.13,
usdConversionRate: 3404.13,
},
- SepoliaETH: {
+ ETH: {
conversionDate: 1721393858.083,
conversionRate: 3414.67,
usdConversionRate: 3414.67,
@@ -166,36 +172,44 @@ describe('Contract Interaction Confirmation', () => {
accountAddress: account.address,
});
- const { getByTestId, queryByTestId, findByTestId } =
+ await act(async () => {
await integrationTestRender({
preloadedState: mockedMetaMaskState,
backgroundConnection: backgroundConnectionMocked,
});
+ });
- expect(getByTestId('header-account-name')).toHaveTextContent(accountName);
- expect(getByTestId('header-network-display-name')).toHaveTextContent(
- 'Chain 5',
+ expect(screen.getByTestId('header-account-name')).toHaveTextContent(
+ accountName,
+ );
+ expect(screen.getByTestId('header-network-display-name')).toHaveTextContent(
+ 'Sepolia',
);
- fireEvent.click(getByTestId('header-info__account-details-button'));
+ fireEvent.click(screen.getByTestId('header-info__account-details-button'));
expect(
- await findByTestId('confirmation-account-details-modal__account-name'),
+ await screen.findByTestId(
+ 'confirmation-account-details-modal__account-name',
+ ),
).toHaveTextContent(accountName);
- expect(getByTestId('address-copy-button-text')).toHaveTextContent(
+ expect(screen.getByTestId('address-copy-button-text')).toHaveTextContent(
'0x0DCD5...3E7bc',
);
expect(
- getByTestId('confirmation-account-details-modal__account-balance'),
- ).toHaveTextContent('1.5827157ETH');
+ screen.getByTestId('confirmation-account-details-modal__account-balance'),
+ ).toHaveTextContent('1.582717SepoliaETH');
let confirmAccountDetailsModalMetricsEvent;
await waitFor(() => {
confirmAccountDetailsModalMetricsEvent =
mockedBackgroundConnection.submitRequestToBackground.mock.calls?.find(
- (call) => call[0] === 'trackMetaMetricsEvent',
+ (call) =>
+ call[0] === 'trackMetaMetricsEvent' &&
+ call[1]?.[0].category === MetaMetricsEventCategory.Confirmations,
);
+
expect(confirmAccountDetailsModalMetricsEvent?.[0]).toBe(
'trackMetaMetricsEvent',
);
@@ -216,12 +230,14 @@ describe('Contract Interaction Confirmation', () => {
);
fireEvent.click(
- getByTestId('confirmation-account-details-modal__close-button'),
+ screen.getByTestId('confirmation-account-details-modal__close-button'),
);
await waitFor(() => {
expect(
- queryByTestId('confirmation-account-details-modal__account-name'),
+ screen.queryByTestId(
+ 'confirmation-account-details-modal__account-name',
+ ),
).not.toBeInTheDocument();
});
});
@@ -238,35 +254,38 @@ describe('Contract Interaction Confirmation', () => {
accountAddress: account.address,
});
- const { getByTestId, getByText, findByTestId } =
+ await act(async () => {
await integrationTestRender({
preloadedState: mockedMetaMaskState,
backgroundConnection: backgroundConnectionMocked,
});
+ });
- expect(getByText('Transaction request')).toBeInTheDocument();
+ expect(screen.getByText('Transaction request')).toBeInTheDocument();
- const simulationSection = getByTestId('simulation-details-layout');
+ const simulationSection = screen.getByTestId('simulation-details-layout');
expect(simulationSection).toBeInTheDocument();
expect(simulationSection).toHaveTextContent('Estimated changes');
- const simulationDetailsRow = await findByTestId('simulation-rows-incoming');
+ const simulationDetailsRow = await screen.findByTestId(
+ 'simulation-rows-incoming',
+ );
expect(simulationSection).toContainElement(simulationDetailsRow);
expect(simulationDetailsRow).toHaveTextContent('You receive');
expect(simulationDetailsRow).toContainElement(
- getByTestId('simulation-details-asset-pill'),
+ screen.getByTestId('simulation-details-asset-pill'),
);
expect(simulationDetailsRow).toContainElement(
- getByTestId('simulation-details-amount-pill'),
+ screen.getByTestId('simulation-details-amount-pill'),
);
- const transactionDetailsSection = getByTestId(
+ const transactionDetailsSection = screen.getByTestId(
'transaction-details-section',
);
expect(transactionDetailsSection).toBeInTheDocument();
expect(transactionDetailsSection).toHaveTextContent('Request from');
expect(transactionDetailsSection).toHaveTextContent('Interacting with');
- const gasFeesSection = getByTestId('gas-fee-section');
+ const gasFeesSection = screen.getByTestId('gas-fee-section');
expect(gasFeesSection).toBeInTheDocument();
const editGasFeesRow =
@@ -278,7 +297,9 @@ describe('Contract Interaction Confirmation', () => {
const editGasFeeNativeCurrency =
within(editGasFeesRow).getByTestId('native-currency');
expect(editGasFeeNativeCurrency).toHaveTextContent('$28.50');
- expect(editGasFeesRow).toContainElement(getByTestId('edit-gas-fee-icon'));
+ expect(editGasFeesRow).toContainElement(
+ screen.getByTestId('edit-gas-fee-icon'),
+ );
const gasFeeSpeed = within(gasFeesSection).getByTestId(
'gas-fee-details-speed',
@@ -306,12 +327,14 @@ describe('Contract Interaction Confirmation', () => {
showConfirmationAdvancedDetails: false,
});
- const { getByTestId } = await integrationTestRender({
- preloadedState: mockedMetaMaskState,
- backgroundConnection: backgroundConnectionMocked,
+ await act(async () => {
+ await integrationTestRender({
+ preloadedState: mockedMetaMaskState,
+ backgroundConnection: backgroundConnectionMocked,
+ });
});
- fireEvent.click(getByTestId('header-advanced-details-button'));
+ fireEvent.click(screen.getByTestId('header-advanced-details-button'));
await waitFor(() => {
expect(
@@ -341,9 +364,11 @@ describe('Contract Interaction Confirmation', () => {
showConfirmationAdvancedDetails: true,
});
- const { getByTestId } = await integrationTestRender({
- preloadedState: mockedMetaMaskState,
- backgroundConnection: backgroundConnectionMocked,
+ await act(async () => {
+ await integrationTestRender({
+ preloadedState: mockedMetaMaskState,
+ backgroundConnection: backgroundConnectionMocked,
+ });
});
await waitFor(() => {
@@ -360,37 +385,41 @@ describe('Contract Interaction Confirmation', () => {
transactionData:
'0x3b4b13810000000000000000000000000000000000000000000000000000000000000001',
contractAddress: '0x076146c765189d51be3160a2140cf80bfc73ad68',
- chainId: '0x5',
+ chainId: '0xaa36a7',
},
]);
});
- const gasFeesSection = getByTestId('gas-fee-section');
- const maxFee = getByTestId('gas-fee-details-max-fee');
+ const gasFeesSection = screen.getByTestId('gas-fee-section');
+ const maxFee = screen.getByTestId('gas-fee-details-max-fee');
expect(gasFeesSection).toContainElement(maxFee);
expect(maxFee).toHaveTextContent('Max fee');
expect(maxFee).toHaveTextContent('0.2313 ETH');
expect(maxFee).toHaveTextContent('$787.37');
- const nonceSection = getByTestId('advanced-details-nonce-section');
+ const nonceSection = screen.getByTestId('advanced-details-nonce-section');
expect(nonceSection).toBeInTheDocument();
expect(nonceSection).toHaveTextContent('Nonce');
expect(nonceSection).toContainElement(
- getByTestId('advanced-details-displayed-nonce'),
- );
- expect(getByTestId('advanced-details-displayed-nonce')).toHaveTextContent(
- '9',
+ screen.getByTestId('advanced-details-displayed-nonce'),
);
+ expect(
+ screen.getByTestId('advanced-details-displayed-nonce'),
+ ).toHaveTextContent('9');
- const dataSection = getByTestId('advanced-details-data-section');
+ const dataSection = screen.getByTestId('advanced-details-data-section');
expect(dataSection).toBeInTheDocument();
- const dataSectionFunction = getByTestId('advanced-details-data-function');
+ const dataSectionFunction = screen.getByTestId(
+ 'advanced-details-data-function',
+ );
expect(dataSection).toContainElement(dataSectionFunction);
expect(dataSectionFunction).toHaveTextContent('Function');
expect(dataSectionFunction).toHaveTextContent('mintNFTs');
- const transactionDataParams = getByTestId('advanced-details-data-param-0');
+ const transactionDataParams = screen.getByTestId(
+ 'advanced-details-data-param-0',
+ );
expect(dataSection).toContainElement(transactionDataParams);
expect(transactionDataParams).toHaveTextContent('Number Of Tokens');
expect(transactionDataParams).toHaveTextContent('1');
@@ -408,15 +437,17 @@ describe('Contract Interaction Confirmation', () => {
account.address,
);
- const { getByText } = await integrationTestRender({
- preloadedState: mockedMetaMaskState,
- backgroundConnection: backgroundConnectionMocked,
+ await act(async () => {
+ await integrationTestRender({
+ preloadedState: mockedMetaMaskState,
+ backgroundConnection: backgroundConnectionMocked,
+ });
});
const headingText = 'This is a deceptive request';
const bodyText =
'If you approve this request, a third party known for scams will take all your assets.';
- expect(getByText(headingText)).toBeInTheDocument();
- expect(getByText(bodyText)).toBeInTheDocument();
+ expect(screen.getByText(headingText)).toBeInTheDocument();
+ expect(screen.getByText(bodyText)).toBeInTheDocument();
});
});
diff --git a/test/integration/confirmations/transactions/erc20-approve.test.tsx b/test/integration/confirmations/transactions/erc20-approve.test.tsx
index 824ca80e0b84..e2466ad8f596 100644
--- a/test/integration/confirmations/transactions/erc20-approve.test.tsx
+++ b/test/integration/confirmations/transactions/erc20-approve.test.tsx
@@ -1,28 +1,21 @@
import { ApprovalType } from '@metamask/controller-utils';
-import { waitFor } from '@testing-library/react';
+import { act, screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
import nock from 'nock';
-import { useIsNFT } from '../../../../ui/pages/confirmations/components/confirm/info/approve/hooks/use-is-nft';
import * as backgroundConnection from '../../../../ui/store/background-connection';
import { integrationTestRender } from '../../../lib/render-helpers';
import mockMetaMaskState from '../../data/integration-init-state.json';
import { createMockImplementation, mock4byte } from '../../helpers';
+import { TokenStandard } from '../../../../shared/constants/transaction';
+import { createTestProviderTools } from '../../../stub/provider';
import { getUnapprovedApproveTransaction } from './transactionDataHelpers';
jest.mock('../../../../ui/store/background-connection', () => ({
...jest.requireActual('../../../../ui/store/background-connection'),
submitRequestToBackground: jest.fn(),
+ callBackgroundMethod: jest.fn(),
}));
-jest.mock(
- '../../../../ui/pages/confirmations/components/confirm/info/approve/hooks/use-is-nft',
- () => ({
- ...jest.requireActual(
- '../../../../ui/pages/confirmations/components/confirm/info/approve/hooks/use-is-nft',
- ),
- useIsNFT: jest.fn(),
- }),
-);
-
const mockedBackgroundConnection = jest.mocked(backgroundConnection);
const backgroundConnectionMocked = {
@@ -31,14 +24,21 @@ const backgroundConnectionMocked = {
export const pendingTransactionId = '48a75190-45ca-11ef-9001-f3886ec2397c';
export const pendingTransactionTime = new Date().getTime();
-const getMetaMaskStateWithUnapprovedApproveTransaction = (
- accountAddress: string,
-) => {
+const getMetaMaskStateWithUnapprovedApproveTransaction = (opts?: {
+ showAdvanceDetails: boolean;
+}) => {
+ const account =
+ mockMetaMaskState.internalAccounts.accounts[
+ mockMetaMaskState.internalAccounts
+ .selectedAccount as keyof typeof mockMetaMaskState.internalAccounts.accounts
+ ];
+
return {
...mockMetaMaskState,
preferences: {
...mockMetaMaskState.preferences,
redesignedConfirmationsEnabled: true,
+ showConfirmationAdvancedDetails: opts?.showAdvanceDetails ?? false,
},
pendingApprovals: {
[pendingTransactionId]: {
@@ -55,9 +55,12 @@ const getMetaMaskStateWithUnapprovedApproveTransaction = (
},
pendingApprovalCount: 1,
knownMethodData: {
- '0x3b4b1381': {
- name: 'Mint NFTs',
+ '0x095ea7b3': {
+ name: 'Approve',
params: [
+ {
+ type: 'address',
+ },
{
type: 'uint256',
},
@@ -66,7 +69,7 @@ const getMetaMaskStateWithUnapprovedApproveTransaction = (
},
transactions: [
getUnapprovedApproveTransaction(
- accountAddress,
+ account.address,
pendingTransactionId,
pendingTransactionTime,
),
@@ -83,7 +86,7 @@ const advancedDetailsMockedRequests = {
decodeTransactionData: {
data: [
{
- name: 'approve',
+ name: 'Approve',
params: [
{
type: 'address',
@@ -109,46 +112,261 @@ const setupSubmitRequestToBackgroundMocks = (
...(mockRequests ?? {}),
}),
);
+
+ mockedBackgroundConnection.callBackgroundMethod.mockImplementation(
+ createMockImplementation({ addKnownMethodData: {} }),
+ );
};
-describe('ERC721 Approve Confirmation', () => {
- let useIsNFTMock;
+describe('ERC20 Approve Confirmation', () => {
+ beforeAll(() => {
+ const { provider } = createTestProviderTools({
+ networkId: 'sepolia',
+ chainId: '0xaa36a7',
+ });
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ global.ethereumProvider = provider as any;
+ });
+
beforeEach(() => {
jest.resetAllMocks();
- setupSubmitRequestToBackgroundMocks();
- const APPROVE_NFT_HEX_SIG = '0x095ea7b3';
- mock4byte(APPROVE_NFT_HEX_SIG);
- useIsNFTMock = jest
- .fn()
- .mockImplementation(() => ({ isNFT: false, decimals: '18' }));
- (useIsNFT as jest.Mock).mockImplementation(useIsNFTMock);
+ setupSubmitRequestToBackgroundMocks({
+ getTokenStandardAndDetails: {
+ standard: TokenStandard.ERC20,
+ },
+ });
+ const APPROVE_ERC20_HEX_SIG = '0x095ea7b3';
+ const APPROVE_ERC20_TEXT_SIG = 'approve(address,uint256)';
+ mock4byte(APPROVE_ERC20_HEX_SIG, APPROVE_ERC20_TEXT_SIG);
});
afterEach(() => {
nock.cleanAll();
});
+ afterAll(() => {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ delete (global as any).ethereumProvider;
+ });
+
+ it('displays spending cap request title', async () => {
+ const mockedMetaMaskState =
+ getMetaMaskStateWithUnapprovedApproveTransaction();
+
+ await act(async () => {
+ await integrationTestRender({
+ preloadedState: mockedMetaMaskState,
+ backgroundConnection: backgroundConnectionMocked,
+ });
+ });
+
+ expect(screen.getByText('Spending cap request')).toBeInTheDocument();
+ expect(
+ screen.getByText('This site wants permission to withdraw your tokens'),
+ ).toBeInTheDocument();
+ });
+
+ it('displays approve simulation section', async () => {
+ const mockedMetaMaskState =
+ getMetaMaskStateWithUnapprovedApproveTransaction();
+
+ await act(async () => {
+ await integrationTestRender({
+ preloadedState: mockedMetaMaskState,
+ backgroundConnection: backgroundConnectionMocked,
+ });
+ });
+
+ const simulationSection = screen.getByTestId(
+ 'confirmation__simulation_section',
+ );
+ expect(simulationSection).toBeInTheDocument();
+
+ // TODO - fix this copy
+ expect(simulationSection).toHaveTextContent(
+ "You're giving someone else permission to withdraw NFTs from your account",
+ );
+ expect(simulationSection).toHaveTextContent('Spending cap');
+ const spendingCapValue = screen.getByTestId('simulation-token-value');
+ expect(simulationSection).toContainElement(spendingCapValue);
+ expect(spendingCapValue).toHaveTextContent('1');
+ expect(simulationSection).toHaveTextContent('0x07614...3ad68');
+ });
+
it('displays approve details with correct data', async () => {
- const account =
- mockMetaMaskState.internalAccounts.accounts[
- mockMetaMaskState.internalAccounts
- .selectedAccount as keyof typeof mockMetaMaskState.internalAccounts.accounts
- ];
+ const testUser = userEvent.setup();
const mockedMetaMaskState =
- getMetaMaskStateWithUnapprovedApproveTransaction(account.address);
+ getMetaMaskStateWithUnapprovedApproveTransaction();
- const { getByText } = await integrationTestRender({
- preloadedState: mockedMetaMaskState,
- backgroundConnection: backgroundConnectionMocked,
+ await act(async () => {
+ await integrationTestRender({
+ preloadedState: mockedMetaMaskState,
+ backgroundConnection: backgroundConnectionMocked,
+ });
});
- await waitFor(() => {
- expect(getByText('Spending cap request')).toBeInTheDocument();
+ const approveDetails = screen.getByTestId('confirmation__approve-details');
+ expect(approveDetails).toBeInTheDocument();
+ const approveDetailsSpender = screen.getByTestId(
+ 'confirmation__approve-spender',
+ );
+
+ expect(approveDetails).toContainElement(approveDetailsSpender);
+ expect(approveDetailsSpender).toHaveTextContent('Spender');
+ expect(approveDetailsSpender).toHaveTextContent('0x2e0D7...5d09B');
+ const spenderTooltip = screen.getByTestId(
+ 'confirmation__approve-spender-tooltip',
+ );
+ expect(approveDetailsSpender).toContainElement(spenderTooltip);
+ await testUser.hover(spenderTooltip);
+ // TODO - fix this copy
+ const spenderTooltipContent = await screen.findByText(
+ 'This is the address that will be able to withdraw your NFTs.',
+ );
+ expect(spenderTooltipContent).toBeInTheDocument();
+
+ const approveDetailsRequestFrom = screen.getByTestId(
+ 'transaction-details-origin-row',
+ );
+ expect(approveDetails).toContainElement(approveDetailsRequestFrom);
+ expect(approveDetailsRequestFrom).toHaveTextContent('Request from');
+ expect(approveDetailsRequestFrom).toHaveTextContent(
+ 'http://localhost:8086/',
+ );
+
+ const approveDetailsRequestFromTooltip = screen.getByTestId(
+ 'transaction-details-origin-row-tooltip',
+ );
+ expect(approveDetailsRequestFrom).toContainElement(
+ approveDetailsRequestFromTooltip,
+ );
+ await testUser.hover(approveDetailsRequestFromTooltip);
+ const requestFromTooltipContent = await screen.findByText(
+ 'This is the site asking for your confirmation.',
+ );
+ expect(requestFromTooltipContent).toBeInTheDocument();
+ });
+
+ it('displays spending cap section with correct data', async () => {
+ const testUser = userEvent.setup();
+
+ const mockedMetaMaskState =
+ getMetaMaskStateWithUnapprovedApproveTransaction();
+
+ await act(async () => {
+ await integrationTestRender({
+ preloadedState: mockedMetaMaskState,
+ backgroundConnection: backgroundConnectionMocked,
+ });
});
- await waitFor(() => {
- expect(getByText('Request from')).toBeInTheDocument();
+ const spendingCapSection = screen.getByTestId(
+ 'confirmation__approve-spending-cap-section',
+ );
+ expect(spendingCapSection).toBeInTheDocument();
+
+ expect(spendingCapSection).toHaveTextContent('Account balance');
+ expect(spendingCapSection).toHaveTextContent('0');
+ const spendingCapGroup = screen.getByTestId(
+ 'confirmation__approve-spending-cap-group',
+ );
+ expect(spendingCapSection).toContainElement(spendingCapGroup);
+ expect(spendingCapGroup).toHaveTextContent('Spending cap');
+ expect(spendingCapGroup).toHaveTextContent('1');
+
+ const spendingCapGroupTooltip = screen.getByTestId(
+ 'confirmation__approve-spending-cap-group-tooltip',
+ );
+ expect(spendingCapGroup).toContainElement(spendingCapGroupTooltip);
+ await testUser.hover(spendingCapGroupTooltip);
+ const requestFromTooltipContent = await screen.findByText(
+ 'This is the amount of tokens the spender will be able to access on your behalf.',
+ );
+ expect(requestFromTooltipContent).toBeInTheDocument();
+ });
+
+ it('displays the advanced transaction details section', async () => {
+ const testUser = userEvent.setup();
+
+ const mockedMetaMaskState =
+ getMetaMaskStateWithUnapprovedApproveTransaction({
+ showAdvanceDetails: true,
+ });
+
+ await act(async () => {
+ await integrationTestRender({
+ preloadedState: mockedMetaMaskState,
+ backgroundConnection: backgroundConnectionMocked,
+ });
});
+
+ const approveDetails = screen.getByTestId('confirmation__approve-details');
+ expect(approveDetails).toBeInTheDocument();
+
+ const approveDetailsRecipient = screen.getByTestId(
+ 'transaction-details-recipient-row',
+ );
+ expect(approveDetails).toContainElement(approveDetailsRecipient);
+ expect(approveDetailsRecipient).toHaveTextContent('Interacting with');
+ expect(approveDetailsRecipient).toHaveTextContent('0x07614...3ad68');
+
+ const approveDetailsRecipientTooltip = screen.getByTestId(
+ 'transaction-details-recipient-row-tooltip',
+ );
+ expect(approveDetailsRecipient).toContainElement(
+ approveDetailsRecipientTooltip,
+ );
+ await testUser.hover(approveDetailsRecipientTooltip);
+ const recipientTooltipContent = await screen.findByText(
+ "This is the contract you're interacting with. Protect yourself from scammers by verifying the details.",
+ );
+ expect(recipientTooltipContent).toBeInTheDocument();
+
+ const approveMethodData = await screen.findByTestId(
+ 'transaction-details-method-data-row',
+ );
+ expect(approveDetails).toContainElement(approveMethodData);
+ expect(approveMethodData).toHaveTextContent('Method');
+ expect(approveMethodData).toHaveTextContent('Approve');
+ const approveMethodDataTooltip = screen.getByTestId(
+ 'transaction-details-method-data-row-tooltip',
+ );
+ expect(approveMethodData).toContainElement(approveMethodDataTooltip);
+ await testUser.hover(approveMethodDataTooltip);
+ const approveMethodDataTooltipContent = await screen.findByText(
+ 'Function executed based on decoded input data.',
+ );
+ expect(approveMethodDataTooltipContent).toBeInTheDocument();
+
+ const approveDetailsNonce = screen.getByTestId(
+ 'advanced-details-nonce-section',
+ );
+ expect(approveDetailsNonce).toBeInTheDocument();
+
+ const dataSection = screen.getByTestId('advanced-details-data-section');
+ expect(dataSection).toBeInTheDocument();
+
+ const dataSectionFunction = screen.getByTestId(
+ 'advanced-details-data-function',
+ );
+ expect(dataSection).toContainElement(dataSectionFunction);
+ expect(dataSectionFunction).toHaveTextContent('Function');
+ expect(dataSectionFunction).toHaveTextContent('Approve');
+
+ const approveDataParams1 = screen.getByTestId(
+ 'advanced-details-data-param-0',
+ );
+ expect(dataSection).toContainElement(approveDataParams1);
+ expect(approveDataParams1).toHaveTextContent('Param #1');
+ expect(approveDataParams1).toHaveTextContent('0x2e0D7...5d09B');
+
+ const approveDataParams2 = screen.getByTestId(
+ 'advanced-details-data-param-1',
+ );
+ expect(dataSection).toContainElement(approveDataParams2);
+ expect(approveDataParams2).toHaveTextContent('Param #2');
+ expect(approveDataParams2).toHaveTextContent('1');
});
});
diff --git a/test/integration/confirmations/transactions/erc721-approve.test.tsx b/test/integration/confirmations/transactions/erc721-approve.test.tsx
index 47f0e2121eb8..8a836dbd7568 100644
--- a/test/integration/confirmations/transactions/erc721-approve.test.tsx
+++ b/test/integration/confirmations/transactions/erc721-approve.test.tsx
@@ -1,28 +1,20 @@
import { ApprovalType } from '@metamask/controller-utils';
-import { waitFor } from '@testing-library/react';
+import { act, screen, waitFor } from '@testing-library/react';
import nock from 'nock';
-import { useIsNFT } from '../../../../ui/pages/confirmations/components/confirm/info/approve/hooks/use-is-nft';
import * as backgroundConnection from '../../../../ui/store/background-connection';
import { integrationTestRender } from '../../../lib/render-helpers';
import mockMetaMaskState from '../../data/integration-init-state.json';
import { createMockImplementation, mock4byte } from '../../helpers';
+import { TokenStandard } from '../../../../shared/constants/transaction';
+import { createTestProviderTools } from '../../../stub/provider';
import { getUnapprovedApproveTransaction } from './transactionDataHelpers';
jest.mock('../../../../ui/store/background-connection', () => ({
...jest.requireActual('../../../../ui/store/background-connection'),
submitRequestToBackground: jest.fn(),
+ callBackgroundMethod: jest.fn(),
}));
-jest.mock(
- '../../../../ui/pages/confirmations/components/confirm/info/approve/hooks/use-is-nft',
- () => ({
- ...jest.requireActual(
- '../../../../ui/pages/confirmations/components/confirm/info/approve/hooks/use-is-nft',
- ),
- useIsNFT: jest.fn(),
- }),
-);
-
const mockedBackgroundConnection = jest.mocked(backgroundConnection);
const backgroundConnectionMocked = {
@@ -55,9 +47,12 @@ const getMetaMaskStateWithUnapprovedApproveTransaction = (
},
pendingApprovalCount: 1,
knownMethodData: {
- '0x3b4b1381': {
- name: 'Mint NFTs',
+ '0x095ea7b3': {
+ name: 'Approve',
params: [
+ {
+ type: 'address',
+ },
{
type: 'uint256',
},
@@ -109,23 +104,43 @@ const setupSubmitRequestToBackgroundMocks = (
...(mockRequests ?? {}),
}),
);
+
+ mockedBackgroundConnection.callBackgroundMethod.mockImplementation(
+ createMockImplementation({ addKnownMethodData: {} }),
+ );
};
describe('ERC721 Approve Confirmation', () => {
- let useIsNFTMock;
+ beforeAll(() => {
+ const { provider } = createTestProviderTools({
+ networkId: 'sepolia',
+ chainId: '0xaa36a7',
+ });
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ global.ethereumProvider = provider as any;
+ });
+
beforeEach(() => {
jest.resetAllMocks();
- setupSubmitRequestToBackgroundMocks();
+ setupSubmitRequestToBackgroundMocks({
+ getTokenStandardAndDetails: {
+ standard: TokenStandard.ERC721,
+ },
+ });
const APPROVE_NFT_HEX_SIG = '0x095ea7b3';
mock4byte(APPROVE_NFT_HEX_SIG);
- useIsNFTMock = jest.fn().mockImplementation(() => ({ isNFT: true }));
- (useIsNFT as jest.Mock).mockImplementation(useIsNFTMock);
});
afterEach(() => {
nock.cleanAll();
});
+ afterAll(() => {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ delete (global as any).ethereumProvider;
+ });
+
it('displays approve details with correct data', async () => {
const account =
mockMetaMaskState.internalAccounts.accounts[
@@ -136,17 +151,19 @@ describe('ERC721 Approve Confirmation', () => {
const mockedMetaMaskState =
getMetaMaskStateWithUnapprovedApproveTransaction(account.address);
- const { getByText } = await integrationTestRender({
- preloadedState: mockedMetaMaskState,
- backgroundConnection: backgroundConnectionMocked,
+ await act(async () => {
+ await integrationTestRender({
+ preloadedState: mockedMetaMaskState,
+ backgroundConnection: backgroundConnectionMocked,
+ });
});
await waitFor(() => {
- expect(getByText('Allowance request')).toBeInTheDocument();
+ expect(screen.getByText('Allowance request')).toBeInTheDocument();
});
await waitFor(() => {
- expect(getByText('Request from')).toBeInTheDocument();
+ expect(screen.getByText('Request from')).toBeInTheDocument();
});
});
});
diff --git a/test/integration/confirmations/transactions/transactionDataHelpers.tsx b/test/integration/confirmations/transactions/transactionDataHelpers.tsx
index 72fc0d2289f3..12550ea5e563 100644
--- a/test/integration/confirmations/transactions/transactionDataHelpers.tsx
+++ b/test/integration/confirmations/transactions/transactionDataHelpers.tsx
@@ -7,7 +7,7 @@ export const getUnapprovedTransaction = (
) => {
return {
actionId: 4256525906,
- chainId: '0x5',
+ chainId: '0xaa36a7',
dappSuggestedGasFees: {
gas: '0x16a92',
},
diff --git a/test/integration/data/integration-init-state.json b/test/integration/data/integration-init-state.json
index 27cd1dcfd83a..212ea5702868 100644
--- a/test/integration/data/integration-init-state.json
+++ b/test/integration/data/integration-init-state.json
@@ -26,18 +26,19 @@
}
},
"accountsByChainId": {
- "0x5": {
+ "0xaa36a7": {
"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc": {
+ "address": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc",
"balance": "0x15f6f0b9d4f8d000"
}
}
},
"addSnapAccountEnabled": false,
"addressBook": {
- "0x5": {
+ "0xaa36a7": {
"0xc42edfcc21ed14dda456aa0756c153f7985d8813": {
"address": "0xc42edfcc21ed14dda456aa0756c153f7985d8813",
- "chainId": "0x5",
+ "chainId": "0xaa36a7",
"isEns": false,
"memo": "",
"name": "Address Book Account 1"
@@ -45,7 +46,7 @@
}
},
"advancedGasFee": {
- "0x5": {
+ "0xaa36a7": {
"maxBaseFee": "75",
"priorityFee": "2"
}
@@ -92,6 +93,17 @@
"createdDate": null,
"schemaName": "ERC721",
"externalLink": null
+ },
+ {
+ "address": "0x495f947276749Ce646f68AC8c248420045cb7b5e",
+ "description": null,
+ "name": "Punk Generator",
+ "logo": null,
+ "symbol": "PUNK",
+ "assetContractType": "non-fungible",
+ "createdDate": null,
+ "schemaName": "ERC1155",
+ "externalLink": null
}
],
"0x5": [
@@ -105,17 +117,6 @@
"createdDate": null,
"schemaName": "ERC721",
"externalLink": null
- },
- {
- "address": "0x495f947276749Ce646f68AC8c248420045cb7b5e",
- "description": null,
- "name": "Punk Generator",
- "logo": null,
- "symbol": "PUNK",
- "assetContractType": "non-fungible",
- "createdDate": null,
- "schemaName": "ERC1155",
- "externalLink": null
}
],
"0x99": [
@@ -155,7 +156,7 @@
"standard": "ERC721"
}
],
- "0xaa36a7": [
+ "0x5": [
{
"address": "0xDc7382Eb0Bc9C352A4CbA23c909bDA01e0206414",
"tokenId": "1",
@@ -165,7 +166,7 @@
"standard": "ERC721"
}
],
- "0x5": [
+ "0xaa36a7": [
{
"address": "0x495f947276749Ce646f68AC8c248420045cb7b5e",
"tokenId": "58076532811975507823669075598676816378162417803895263482849101575514658701313",
@@ -395,7 +396,7 @@
"networkCongestion": 0.10625
},
"gasFeeEstimatesByChainId": {
- "0x5": {
+ "0xaa36a7": {
"estimatedGasFeeTimeBounds": {
"lowerTimeBound": 15000,
"upperTimeBound": 60000
@@ -462,7 +463,7 @@
"0xe708": false,
"0xfa": true,
"0x5": false,
- "0xaa36a7": true,
+ "0xaa36a7": false,
"0xe704": true
},
"internalAccounts": {
@@ -669,6 +670,13 @@
"nickname": "Chain 5",
"ticker": "ETH",
"type": "rpc"
+ },
+ "sepolia": {
+ "type": "rpc",
+ "chainId": "0xaa36a7",
+ "ticker": "ETH",
+ "nickname": "Sepolia",
+ "id": "sepolia"
}
},
"networksMetadata": {
@@ -693,7 +701,7 @@
},
"nftsDropdownState": {
"0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc": {
- "0x5": {
+ "0xaa36a7": {
"0x495f947276749Ce646f68AC8c248420045cb7b5e": false
}
}
@@ -756,16 +764,16 @@
"previousAppVersion": "11.14.4",
"previousMigrationVersion": 112,
"providerConfig": {
- "type": "rpc",
- "nickname": "goerli",
- "chainId": "0x5",
+ "type": "sepolia",
+ "nickname": "sepolia",
+ "chainId": "0xaa36a7",
"ticker": "ETH",
- "id": "chain5"
+ "id": "sepolia"
},
"securityAlertsEnabled": true,
"seedPhraseBackedUp": true,
"selectedAddress": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc",
- "selectedNetworkClientId": "goerli-network-id",
+ "selectedNetworkClientId": "sepolia",
"showAccountBanner": false,
"showBetaHeader": false,
"showNetworkBanner": true,
@@ -778,7 +786,7 @@
"liveness": true,
"smartTransactions": {
"0x1": [],
- "0x5": []
+ "0xaa36a7": []
},
"userOptInV2": true
},
@@ -1271,7 +1279,7 @@
"id": 3387511061307736,
"time": 1528133130531,
"status": "confirmed",
- "chainId": "0x5",
+ "chainId": "0xaa36a7",
"loadingDefaults": false,
"txParams": {
"from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62",
@@ -1286,7 +1294,7 @@
"id": 3387511061307736,
"time": 1528133130531,
"status": "unapproved",
- "chainId": "0x5",
+ "chainId": "0xaa36a7",
"loadingDefaults": true,
"txParams": {
"from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62",
@@ -1403,7 +1411,7 @@
"id": 3387511061307737,
"time": 1528133149983,
"status": "confirmed",
- "chainId": "0x5",
+ "chainId": "0xaa36a7",
"loadingDefaults": false,
"txParams": {
"from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62",
@@ -1418,7 +1426,7 @@
"id": 3387511061307737,
"time": 1528133149983,
"status": "unapproved",
- "chainId": "0x5",
+ "chainId": "0xaa36a7",
"loadingDefaults": true,
"txParams": {
"from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62",
@@ -1535,7 +1543,7 @@
"id": 3387511061307738,
"time": 1528133180635,
"status": "confirmed",
- "chainId": "0x5",
+ "chainId": "0xaa36a7",
"loadingDefaults": false,
"txParams": {
"from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62",
@@ -1550,7 +1558,7 @@
"id": 3387511061307738,
"time": 1528133180635,
"status": "unapproved",
- "chainId": "0x5",
+ "chainId": "0xaa36a7",
"loadingDefaults": true,
"txParams": {
"from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62",
@@ -1667,7 +1675,7 @@
"id": 3387511061307739,
"time": 1528133223918,
"status": "confirmed",
- "chainId": "0x5",
+ "chainId": "0xaa36a7",
"loadingDefaults": false,
"txParams": {
"from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62",
@@ -1683,7 +1691,7 @@
"id": 3387511061307739,
"time": 1528133223918,
"status": "unapproved",
- "chainId": "0x5",
+ "chainId": "0xaa36a7",
"loadingDefaults": true,
"txParams": {
"from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62",
@@ -1804,7 +1812,7 @@
"id": 3387511061307740,
"time": 1528133291381,
"status": "confirmed",
- "chainId": "0x5",
+ "chainId": "0xaa36a7",
"loadingDefaults": false,
"txParams": {
"from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62",
@@ -1820,7 +1828,7 @@
"id": 3387511061307740,
"time": 1528133291381,
"status": "unapproved",
- "chainId": "0x5",
+ "chainId": "0xaa36a7",
"loadingDefaults": true,
"txParams": {
"from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62",
@@ -1938,7 +1946,7 @@
"id": 3387511061307741,
"time": 1528133318440,
"status": "rejected",
- "chainId": "0x5",
+ "chainId": "0xaa36a7",
"loadingDefaults": false,
"txParams": {
"from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62",
@@ -1952,7 +1960,7 @@
"id": 3387511061307741,
"time": 1528133318440,
"status": "unapproved",
- "chainId": "0x5",
+ "chainId": "0xaa36a7",
"loadingDefaults": true,
"txParams": {
"from": "0x3b222de3aaba8ec9771ca9e9af5d8ed757fb7f62",
@@ -2029,12 +2037,12 @@
"useTokenDetection": false,
"useTransactionSimulations": true,
"usedNetworks": {
- "0x5": {
- "rpcUrl": "https://goerli.infura.io/v3/8f8f7f9f6f4c4f3e8f8f7f9f6f4c4f3e",
- "chainId": "0x5",
- "nickname": "Goerli Test Network",
+ "0xaa36a7": {
+ "rpcUrl": "https://sepolia.infura.io/v3/8f8f7f9f6f4c4f3e8f8f7f9f6f4c4f3e",
+ "chainId": "0xaa36a7",
+ "nickname": "Sepolia Test Network",
"ticker": "ETH",
- "blockExplorerUrl": "https://goerli.etherscan.io"
+ "blockExplorerUrl": "https://sepolia.etherscan.io"
}
},
"userOperations": {},
diff --git a/test/integration/helpers.tsx b/test/integration/helpers.tsx
index d975c5adc594..2576d282a341 100644
--- a/test/integration/helpers.tsx
+++ b/test/integration/helpers.tsx
@@ -9,7 +9,7 @@ export const createMockImplementation = (requests: Record) => {
};
};
-export function mock4byte(hexSignature: string) {
+export function mock4byte(hexSignature: string, textSignature?: string) {
const mockEndpoint = nock('https://www.4byte.directory:443', {
encodedQueryParams: true,
})
@@ -21,7 +21,7 @@ export function mock4byte(hexSignature: string) {
{
id: 235447,
created_at: '2021-09-14T02:07:09.805000Z',
- text_signature: 'mintNFTs(uint256)',
+ text_signature: textSignature ?? 'mintNFTs(uint256)',
hex_signature: hexSignature,
bytes_signature: ';K\u0013 ',
},
diff --git a/ui/components/app/confirm/info/row/row.tsx b/ui/components/app/confirm/info/row/row.tsx
index 6b6470c98017..0dd0b9b110b8 100644
--- a/ui/components/app/confirm/info/row/row.tsx
+++ b/ui/components/app/confirm/info/row/row.tsx
@@ -128,6 +128,9 @@ export const ConfirmInfoRow: React.FC = ({
marginLeft={1}
color={TOOLTIP_ICON_COLORS[variant] as unknown as IconColor}
size={IconSize.Sm}
+ {...(dataTestId
+ ? { 'data-testid': `${dataTestId}-tooltip` }
+ : {})}
/>
)}
diff --git a/ui/pages/confirmations/components/confirm/info/approve/__snapshots__/approve.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/approve/__snapshots__/approve.test.tsx.snap
index 6f09eea933f4..ee8bff7a53dd 100644
--- a/ui/pages/confirmations/components/confirm/info/approve/__snapshots__/approve.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/info/approve/__snapshots__/approve.test.tsx.snap
@@ -98,9 +98,11 @@ exports[` renders component for approve request 1`] = `
renders component for approve request 1`] = `
>
@@ -214,6 +217,7 @@ exports[`
renders component for approve request 1`] = `
>
@@ -254,6 +258,7 @@ exports[` renders component for approve request 1`] = `
>
@@ -320,6 +325,7 @@ exports[` renders component for approve request 1`] = `
renders component for approve request 1`] = `
/>
renders component for approve request 1`] = `
>
@@ -430,6 +438,7 @@ exports[`
renders component for approve request 1`] = `
>
@@ -529,6 +538,7 @@ exports[` renders component for approve request 1`] = `
>
@@ -674,6 +684,7 @@ exports[` renders component for approve request 1`] = `
>
@@ -762,6 +773,7 @@ exports[` renders component for approve request 1`] = `
>
diff --git a/ui/pages/confirmations/components/confirm/info/approve/approve-details/__snapshots__/approve-details.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/approve/approve-details/__snapshots__/approve-details.test.tsx.snap
index c31eb7dcfbd0..5491908cdffd 100644
--- a/ui/pages/confirmations/components/confirm/info/approve/approve-details/__snapshots__/approve-details.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/info/approve/approve-details/__snapshots__/approve-details.test.tsx.snap
@@ -4,6 +4,7 @@ exports[` renders component for approve details 1`] = `
{
return (
<>
-
+
@@ -50,7 +54,7 @@ export const ApproveDetails = () => {
);
return (
-
+
{showAdvancedDetails && (
diff --git a/ui/pages/confirmations/components/confirm/info/approve/spending-cap/__snapshots__/spending-cap.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/approve/spending-cap/__snapshots__/spending-cap.test.tsx.snap
index d249b4ba843b..dafe44df8e70 100644
--- a/ui/pages/confirmations/components/confirm/info/approve/spending-cap/__snapshots__/spending-cap.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/info/approve/spending-cap/__snapshots__/spending-cap.test.tsx.snap
@@ -4,6 +4,7 @@ exports[` renders component 1`] = `
renders component 1`] = `
/>
renders component 1`] = `
>
diff --git a/ui/pages/confirmations/components/confirm/info/approve/spending-cap/spending-cap.tsx b/ui/pages/confirmations/components/confirm/info/approve/spending-cap/spending-cap.tsx
index 73f0ef773fa0..2ebd9d8e7e4e 100644
--- a/ui/pages/confirmations/components/confirm/info/approve/spending-cap/spending-cap.tsx
+++ b/ui/pages/confirmations/components/confirm/info/approve/spending-cap/spending-cap.tsx
@@ -62,6 +62,7 @@ const SpendingCapGroup = ({
{spendingCap === SPENDING_CAP_UNLIMITED_MSG ? (
{SpendingCapElement}
@@ -105,7 +106,7 @@ export const SpendingCap = ({
}
return (
-
+
diff --git a/ui/pages/confirmations/components/confirm/info/base-transaction-info/__snapshots__/base-transaction-info.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/base-transaction-info/__snapshots__/base-transaction-info.test.tsx.snap
index de72d2c1cfac..5a5e4583cf3d 100644
--- a/ui/pages/confirmations/components/confirm/info/base-transaction-info/__snapshots__/base-transaction-info.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/info/base-transaction-info/__snapshots__/base-transaction-info.test.tsx.snap
@@ -113,6 +113,7 @@ exports[` renders component for contract interaction requ
>
@@ -153,6 +154,7 @@ exports[`
renders component for contract interaction requ
>
@@ -246,6 +248,7 @@ exports[` renders component for contract interaction requ
>
@@ -473,6 +476,7 @@ exports[`
renders component for contract interaction requ
>
@@ -513,6 +517,7 @@ exports[`
renders component for contract interaction requ
>
@@ -606,6 +611,7 @@ exports[` renders component for contract interaction requ
>
@@ -830,6 +836,7 @@ exports[` renders component for contract interaction requ
>
@@ -870,6 +877,7 @@ exports[` renders component for contract interaction requ
>
@@ -963,6 +971,7 @@ exports[` renders component for contract interaction requ
>
diff --git a/ui/pages/confirmations/components/confirm/info/shared/edit-gas-fees-row/__snapshots__/edit-gas-fees-row.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/shared/edit-gas-fees-row/__snapshots__/edit-gas-fees-row.test.tsx.snap
index f0702978aa6c..0508381f9fbb 100644
--- a/ui/pages/confirmations/components/confirm/info/shared/edit-gas-fees-row/__snapshots__/edit-gas-fees-row.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/info/shared/edit-gas-fees-row/__snapshots__/edit-gas-fees-row.test.tsx.snap
@@ -27,6 +27,7 @@ exports[` renders component 1`] = `
>
diff --git a/ui/pages/confirmations/components/confirm/info/shared/gas-fees-details/__snapshots__/gas-fees-details.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/shared/gas-fees-details/__snapshots__/gas-fees-details.test.tsx.snap
index f797ffdb66c8..9b01388f94f3 100644
--- a/ui/pages/confirmations/components/confirm/info/shared/gas-fees-details/__snapshots__/gas-fees-details.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/info/shared/gas-fees-details/__snapshots__/gas-fees-details.test.tsx.snap
@@ -27,6 +27,7 @@ exports[` renders component for gas fees section 1`] = `
>
diff --git a/ui/pages/confirmations/components/confirm/info/shared/gas-fees-section/__snapshots__/gas-fees-section.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/shared/gas-fees-section/__snapshots__/gas-fees-section.test.tsx.snap
index 42bb2073ffcf..6a3e7cb058d9 100644
--- a/ui/pages/confirmations/components/confirm/info/shared/gas-fees-section/__snapshots__/gas-fees-section.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/info/shared/gas-fees-section/__snapshots__/gas-fees-section.test.tsx.snap
@@ -33,6 +33,7 @@ exports[` renders component for gas fees section 1`] = `
>
diff --git a/ui/pages/confirmations/components/confirm/info/shared/transaction-data/__snapshots__/transaction-data.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/shared/transaction-data/__snapshots__/transaction-data.test.tsx.snap
index 02da6945d64a..22bd56481f11 100644
--- a/ui/pages/confirmations/components/confirm/info/shared/transaction-data/__snapshots__/transaction-data.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/info/shared/transaction-data/__snapshots__/transaction-data.test.tsx.snap
@@ -102,6 +102,7 @@ exports[`TransactionData renders decoded data with names and descriptions 1`] =
>
@@ -154,6 +155,7 @@ exports[`TransactionData renders decoded data with names and descriptions 1`] =
>
@@ -250,6 +252,7 @@ exports[`TransactionData renders decoded data with names and descriptions 1`] =
>
@@ -302,6 +305,7 @@ exports[`TransactionData renders decoded data with names and descriptions 1`] =
>
@@ -343,6 +347,7 @@ exports[`TransactionData renders decoded data with names and descriptions 1`] =
>
@@ -384,6 +389,7 @@ exports[`TransactionData renders decoded data with names and descriptions 1`] =
>
@@ -502,6 +508,7 @@ exports[`TransactionData renders decoded data with names and descriptions 1`] =
>
@@ -598,6 +605,7 @@ exports[`TransactionData renders decoded data with names and descriptions 1`] =
>
@@ -650,6 +658,7 @@ exports[`TransactionData renders decoded data with names and descriptions 1`] =
>
@@ -702,6 +711,7 @@ exports[`TransactionData renders decoded data with names and descriptions 1`] =
>
@@ -798,6 +808,7 @@ exports[`TransactionData renders decoded data with names and descriptions 1`] =
>
@@ -850,6 +861,7 @@ exports[`TransactionData renders decoded data with names and descriptions 1`] =
>
@@ -902,6 +914,7 @@ exports[`TransactionData renders decoded data with names and descriptions 1`] =
>
@@ -1007,6 +1020,7 @@ exports[`TransactionData renders decoded data with no names 1`] = `
>
@@ -1048,6 +1062,7 @@ exports[`TransactionData renders decoded data with no names 1`] = `
>
@@ -1100,6 +1115,7 @@ exports[`TransactionData renders decoded data with no names 1`] = `
>
@@ -1174,6 +1190,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1218,6 +1235,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1270,6 +1288,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1304,6 +1323,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1338,6 +1358,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1372,6 +1393,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1424,6 +1446,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1465,6 +1488,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1506,6 +1530,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1548,6 +1573,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1582,6 +1608,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1634,6 +1661,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1675,6 +1703,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1716,6 +1745,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1758,6 +1788,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1792,6 +1823,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1844,6 +1876,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1885,6 +1918,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1926,6 +1960,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -1969,6 +2004,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -2021,6 +2057,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
@@ -2063,6 +2100,7 @@ exports[`TransactionData renders decoded data with tuples and arrays 1`] = `
>
diff --git a/ui/pages/confirmations/components/confirm/info/shared/transaction-details/__snapshots__/transaction-details.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/shared/transaction-details/__snapshots__/transaction-details.test.tsx.snap
index b65f3e74f8b8..8652c8f67128 100644
--- a/ui/pages/confirmations/components/confirm/info/shared/transaction-details/__snapshots__/transaction-details.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/info/shared/transaction-details/__snapshots__/transaction-details.test.tsx.snap
@@ -40,6 +40,7 @@ exports[` renders component for transaction details 1`] =
>
@@ -80,6 +81,7 @@ exports[` renders component for transaction details 1`] =
>
From 1a6f212e57203438f0daff970e03a42483ecfdb6 Mon Sep 17 00:00:00 2001
From: Derek Brans
Date: Wed, 18 Sep 2024 08:39:05 -0400
Subject: [PATCH 16/37] chore: smart-transactions code domain (#26948)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
This PR establishes the `ui/pages/smart-transactions` code domain,
following the guidance in [this
proposal](https://docs.google.com/document/d/1dzgWc1LCkYz2lZZ6X8SOaj23iaGYVQ2zJ1FVpOxsU-o/edit).
Moved | To ui/pages/smart-transactions/
-- | --
ui/components/app/smart-transactions/smart-transactions-opt-in-modal.tsx
| components/smart-transactions-opt-in-modal.tsx
The following files will be left in place.
| Left in place | Reason |
|---------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|
app/scripts/lib/transaction/smart-transactions.ts | background code
shared/constants/smartTransactions.ts | shared with background
|
`ui/components/app/transaction-list-item/smart-transaction-list-item.component.js`
| Specific to the transaction list. |
|
`ui/pages/confirmations/confirmation/templates/smart-transaction-status-page.js`
| Belongs with other confirmation templates. |
| `ui/pages/swaps/smart-transaction-status/smart-transaction-status.js`
| Swaps-focused. Will be replaced by regular STX status screen once
swaps moves to regular STX. |
### STX-related code in other files
The following files contain stx-related code, which may be extracted and
moved into the smart-transactions code domain at a later time.
| Path | STX-Related Code |
|------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|
| `app/scripts/metamask-controller.js` | We use the STX controller there
`new SmartTransactionsController`. `*// Smart Transactions` section* |
| `ui/ducks/swaps/swaps.js` | A few functions related to STX:
`fetchSmartTransactionsLiveness`, `signAndSendSmartTransaction`,
`setSmartTransactionsRefreshInterval`, etc. |
| `ui/store/actions.ts` | `fetchSmartTransactionsLiveness` and other STX
functions |
|
`ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.container.js`
| STX is used from this component |
| `ui/pages/settings/advanced-tab/advanced-tab.component.js` | Advanced
Settings that include STX option |
| `ui/pages/swaps/swaps.util.ts` | `getFeeForSmartTransaction` |
| `ui/pages/swaps/prepare-swap-page/review-quote.js` | Uses STX in Swaps
|
| `ui/selectors/transactions.js` |
`allowedSwapsSmartTransactionStatusesForActivityList` |
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/26948?quickstart=1)
## **Related issues**
Fixes:
## **Manual testing steps**
1. Installed extension
2. Added account with crypto
3. Verify STX opt-in-modal
4. Send a smart transaction
## **Screenshots/Recordings**
### **Before**
### **After**
![image](https://github.com/user-attachments/assets/6d610e0d-48b8-43e5-9dff-774481966e77)
![image](https://github.com/user-attachments/assets/4a8f5c17-4e2e-402b-84ca-61c95ed08948)
![image](https://github.com/user-attachments/assets/0eae012c-4cfe-4272-94c2-12b7519af1cb)
![image](https://github.com/user-attachments/assets/2cd232e6-d279-4894-b2df-5fcee0a8a0c9)
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
---
ui/components/app/app-components.scss | 1 -
ui/pages/home/home.component.js | 2 +-
ui/pages/pages.scss | 2 +-
.../__snapshots__/smart-transactions-opt-in-modal.test.tsx.snap | 0
.../smart-transactions/components}/index.scss | 0
.../components}/smart-transactions-opt-in-modal.test.tsx | 0
.../components}/smart-transactions-opt-in-modal.tsx | 2 +-
ui/pages/smart-transactions/index.scss | 2 ++
8 files changed, 5 insertions(+), 4 deletions(-)
rename ui/{components/app/smart-transactions => pages/smart-transactions/components}/__snapshots__/smart-transactions-opt-in-modal.test.tsx.snap (100%)
rename ui/{components/app/smart-transactions => pages/smart-transactions/components}/index.scss (100%)
rename ui/{components/app/smart-transactions => pages/smart-transactions/components}/smart-transactions-opt-in-modal.test.tsx (100%)
rename ui/{components/app/smart-transactions => pages/smart-transactions/components}/smart-transactions-opt-in-modal.tsx (99%)
create mode 100644 ui/pages/smart-transactions/index.scss
diff --git a/ui/components/app/app-components.scss b/ui/components/app/app-components.scss
index cc9a08a53f1d..c5083af45104 100644
--- a/ui/components/app/app-components.scss
+++ b/ui/components/app/app-components.scss
@@ -51,7 +51,6 @@
@import 'recovery-phrase-reminder/index';
@import 'step-progress-bar/index.scss';
@import 'selected-account/index';
-@import 'smart-transactions/index';
@import 'srp-input/srp-input';
@import 'snaps/snap-privacy-warning/index';
@import 'tab-bar/index';
diff --git a/ui/pages/home/home.component.js b/ui/pages/home/home.component.js
index 1c746869ad10..19b76a881c6c 100644
--- a/ui/pages/home/home.component.js
+++ b/ui/pages/home/home.component.js
@@ -13,7 +13,7 @@ import TermsOfUsePopup from '../../components/app/terms-of-use-popup';
import RecoveryPhraseReminder from '../../components/app/recovery-phrase-reminder';
import WhatsNewPopup from '../../components/app/whats-new-popup';
import { FirstTimeFlowType } from '../../../shared/constants/onboarding';
-import SmartTransactionsOptInModal from '../../components/app/smart-transactions/smart-transactions-opt-in-modal';
+import SmartTransactionsOptInModal from '../smart-transactions/components/smart-transactions-opt-in-modal';
///: END:ONLY_INCLUDE_IF
import HomeNotification from '../../components/app/home-notification';
import MultipleNotifications from '../../components/app/multiple-notifications';
diff --git a/ui/pages/pages.scss b/ui/pages/pages.scss
index 01641f29774a..2578286032d2 100644
--- a/ui/pages/pages.scss
+++ b/ui/pages/pages.scss
@@ -22,10 +22,10 @@
@import 'onboarding-flow/index';
@import 'permissions-connect/index';
@import 'settings/index';
+@import 'smart-transactions/index';
@import 'snaps/snaps-list/index';
@import 'snaps/snap-view/index';
@import 'create-snap-account/index';
-@import 'smart-transactions/smart-transaction-status-page/index';
@import 'remove-snap-account/index';
@import 'swaps/index';
@import 'token-details/index';
diff --git a/ui/components/app/smart-transactions/__snapshots__/smart-transactions-opt-in-modal.test.tsx.snap b/ui/pages/smart-transactions/components/__snapshots__/smart-transactions-opt-in-modal.test.tsx.snap
similarity index 100%
rename from ui/components/app/smart-transactions/__snapshots__/smart-transactions-opt-in-modal.test.tsx.snap
rename to ui/pages/smart-transactions/components/__snapshots__/smart-transactions-opt-in-modal.test.tsx.snap
diff --git a/ui/components/app/smart-transactions/index.scss b/ui/pages/smart-transactions/components/index.scss
similarity index 100%
rename from ui/components/app/smart-transactions/index.scss
rename to ui/pages/smart-transactions/components/index.scss
diff --git a/ui/components/app/smart-transactions/smart-transactions-opt-in-modal.test.tsx b/ui/pages/smart-transactions/components/smart-transactions-opt-in-modal.test.tsx
similarity index 100%
rename from ui/components/app/smart-transactions/smart-transactions-opt-in-modal.test.tsx
rename to ui/pages/smart-transactions/components/smart-transactions-opt-in-modal.test.tsx
diff --git a/ui/components/app/smart-transactions/smart-transactions-opt-in-modal.tsx b/ui/pages/smart-transactions/components/smart-transactions-opt-in-modal.tsx
similarity index 99%
rename from ui/components/app/smart-transactions/smart-transactions-opt-in-modal.tsx
rename to ui/pages/smart-transactions/components/smart-transactions-opt-in-modal.tsx
index 5b8ff09f9237..78055de42831 100644
--- a/ui/components/app/smart-transactions/smart-transactions-opt-in-modal.tsx
+++ b/ui/pages/smart-transactions/components/smart-transactions-opt-in-modal.tsx
@@ -27,7 +27,7 @@ import {
ButtonLinkSize,
Icon,
IconName,
-} from '../../component-library';
+} from '../../../components/component-library';
import { setSmartTransactionsOptInStatus } from '../../../store/actions';
import { SMART_TRANSACTIONS_LEARN_MORE_URL } from '../../../../shared/constants/smartTransactions';
diff --git a/ui/pages/smart-transactions/index.scss b/ui/pages/smart-transactions/index.scss
new file mode 100644
index 000000000000..8ef1b35cd611
--- /dev/null
+++ b/ui/pages/smart-transactions/index.scss
@@ -0,0 +1,2 @@
+@import './smart-transaction-status-page/index';
+@import './components/index';
From 313adea121a00259203d22e19f9d5b7a6efde8b8 Mon Sep 17 00:00:00 2001
From: Pedro Figueiredo
Date: Wed, 18 Sep 2024 14:56:23 +0100
Subject: [PATCH 17/37] fix: Estimated fee in redesigned screens (#27247)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
`maxFeePerGas`, `maxPriorityFeePerGas` and `estimatedBaseFee` are
decimal values that should be converted before being used inside
`multiplyHexes` and `addHexes`. `estimatedBaseFee` also needs to be
converted to wei.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27247?quickstart=1)
## **Related issues**
Fixes:
## **Manual testing steps**
1. Go to this page...
2.
3.
## **Screenshots/Recordings**
### **Before**
#### Old Flow
#### Redesigned Flow
### **After**
#### Redesigned Flow
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
---
shared/modules/conversion.utils.ts | 2 +-
.../transactions/contract-interaction.test.tsx | 8 ++++----
.../info/approve/__snapshots__/approve.test.tsx.snap | 8 ++++----
.../base-transaction-info.test.tsx.snap | 12 ++++++------
.../confirm/info/hooks/useFeeCalculations.test.ts | 12 ++++++------
.../confirm/info/hooks/useFeeCalculations.ts | 10 ++++++----
.../__snapshots__/gas-fees-details.test.tsx.snap | 4 ++--
.../__snapshots__/gas-fees-section.test.tsx.snap | 4 ++--
8 files changed, 31 insertions(+), 29 deletions(-)
diff --git a/shared/modules/conversion.utils.ts b/shared/modules/conversion.utils.ts
index d9fd2262f843..75da336eb8e6 100644
--- a/shared/modules/conversion.utils.ts
+++ b/shared/modules/conversion.utils.ts
@@ -4,7 +4,7 @@ import { addHexPrefix, BN } from 'ethereumjs-util';
import { EtherDenomination } from '../constants/common';
import { Numeric, NumericValue } from './Numeric';
-export function decGWEIToHexWEI(decGWEI: number) {
+export function decGWEIToHexWEI(decGWEI: NumericValue) {
return new Numeric(decGWEI, 10, EtherDenomination.GWEI)
.toBase(16)
.toDenomination(EtherDenomination.WEI)
diff --git a/test/integration/confirmations/transactions/contract-interaction.test.tsx b/test/integration/confirmations/transactions/contract-interaction.test.tsx
index cea1ed6f54bc..cd5953db50b8 100644
--- a/test/integration/confirmations/transactions/contract-interaction.test.tsx
+++ b/test/integration/confirmations/transactions/contract-interaction.test.tsx
@@ -293,10 +293,10 @@ describe('Contract Interaction Confirmation', () => {
expect(editGasFeesRow).toHaveTextContent('Network fee');
const firstGasField = within(editGasFeesRow).getByTestId('first-gas-field');
- expect(firstGasField).toHaveTextContent('0.0084 ETH');
+ expect(firstGasField).toHaveTextContent('0.0001 ETH');
const editGasFeeNativeCurrency =
within(editGasFeesRow).getByTestId('native-currency');
- expect(editGasFeeNativeCurrency).toHaveTextContent('$28.50');
+ expect(editGasFeeNativeCurrency).toHaveTextContent('$0.47');
expect(editGasFeesRow).toContainElement(
screen.getByTestId('edit-gas-fee-icon'),
);
@@ -394,8 +394,8 @@ describe('Contract Interaction Confirmation', () => {
const maxFee = screen.getByTestId('gas-fee-details-max-fee');
expect(gasFeesSection).toContainElement(maxFee);
expect(maxFee).toHaveTextContent('Max fee');
- expect(maxFee).toHaveTextContent('0.2313 ETH');
- expect(maxFee).toHaveTextContent('$787.37');
+ expect(maxFee).toHaveTextContent('0.0023 ETH');
+ expect(maxFee).toHaveTextContent('$7.72');
const nonceSection = screen.getByTestId('advanced-details-nonce-section');
expect(nonceSection).toBeInTheDocument();
diff --git a/ui/pages/confirmations/components/confirm/info/approve/__snapshots__/approve.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/approve/__snapshots__/approve.test.tsx.snap
index ee8bff7a53dd..34fd469e0571 100644
--- a/ui/pages/confirmations/components/confirm/info/approve/__snapshots__/approve.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/info/approve/__snapshots__/approve.test.tsx.snap
@@ -451,13 +451,13 @@ exports[` renders component for approve request 1`] = `
class="mm-box mm-text mm-text--body-md mm-box--margin-right-1 mm-box--color-text-default"
data-testid="first-gas-field"
>
- 0.004 ETH
+ 0.0001 ETH
- $2.20
+ $0.04
renders component for approve request 1`] = `
- 0.1094 ETH
+ 0.0011 ETH
- $60.83
+ $0.60
diff --git a/ui/pages/confirmations/components/confirm/info/base-transaction-info/__snapshots__/base-transaction-info.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/base-transaction-info/__snapshots__/base-transaction-info.test.tsx.snap
index 5a5e4583cf3d..127e5a8311f7 100644
--- a/ui/pages/confirmations/components/confirm/info/base-transaction-info/__snapshots__/base-transaction-info.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/info/base-transaction-info/__snapshots__/base-transaction-info.test.tsx.snap
@@ -261,13 +261,13 @@ exports[` renders component for contract interaction requ
class="mm-box mm-text mm-text--body-md mm-box--margin-right-1 mm-box--color-text-default"
data-testid="first-gas-field"
>
- 0.004 ETH
+ 0.0001 ETH
- $2.20
+ $0.04
renders component for contract interaction requ
class="mm-box mm-text mm-text--body-md mm-box--margin-right-1 mm-box--color-text-default"
data-testid="first-gas-field"
>
- 0.004 ETH
+ 0.0001 ETH
- $2.20
+ $0.04
renders component for contract interaction requ
class="mm-box mm-text mm-text--body-md mm-box--margin-right-1 mm-box--color-text-default"
data-testid="first-gas-field"
>
- 0.004 ETH
+ 0.0001 ETH
- $2.20
+ $0.04