From 1c8b4bb27ad6c06f38f54a3f03585c203c97aba8 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Fri, 30 Jun 2023 12:40:58 -0230 Subject: [PATCH 001/172] Version v10.34.0 --- CHANGELOG.md | 5 ++++- package.json | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dc5fce18..ca6587539 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [10.34.0] + ## [10.33.0] ### Added - UI Upgrade ([#18903](https://github.com/MetaMask/metamask-extension/pull/18903)) @@ -3825,7 +3827,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Uncategorized - Added the ability to restore accounts from seed words. -[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.33.0...HEAD +[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.34.0...HEAD +[10.33.0]: https://github.com/MetaMask/metamask-extension/compare/v10.33.0...v10.34.0 [10.33.0]: https://github.com/MetaMask/metamask-extension/compare/v10.32.0...v10.33.0 [10.32.0]: https://github.com/MetaMask/metamask-extension/compare/v10.31.1...v10.32.0 [10.31.1]: https://github.com/MetaMask/metamask-extension/compare/v10.31.0...v10.31.1 diff --git a/package.json b/package.json index 123d68999..5b7fd1fdd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "metamask-crx", - "version": "10.33.0", + "version": "10.34.0", "private": true, "repository": { "type": "git", From 96f2ab4dae3746e3c5cecb3291b310997dd6a215 Mon Sep 17 00:00:00 2001 From: George Weiler Date: Fri, 7 Jul 2023 03:29:35 -0600 Subject: [PATCH 002/172] feat: adds linea mainnet buyable support in anticipation of July 11 launch (#19854) * feat: adds linea mainnet support in anticipation of July 11 launch * chore: fixes linting issue * chore: adds comma for linting --------- Co-authored-by: Pedro Pablo Aste Kompen Co-authored-by: Dan J Miller --- shared/constants/network.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shared/constants/network.ts b/shared/constants/network.ts index b25353dbe..6d5058aac 100644 --- a/shared/constants/network.ts +++ b/shared/constants/network.ts @@ -549,7 +549,6 @@ export const BUYABLE_CHAINS_MAP: { | typeof CHAIN_IDS.FANTOM_TESTNET | typeof CHAIN_IDS.MOONBEAM_TESTNET | typeof CHAIN_IDS.LINEA_GOERLI - | typeof CHAIN_IDS.LINEA_MAINNET | typeof CHAIN_IDS.GOERLI >]: BuyableChainSettings; } = { @@ -613,6 +612,10 @@ export const BUYABLE_CHAINS_MAP: { nativeCurrency: CURRENCY_SYMBOLS.PALM, network: 'palm', }, + [CHAIN_IDS.LINEA_MAINNET]: { + nativeCurrency: CURRENCY_SYMBOLS.ETH, + network: 'linea', + }, }; export const FEATURED_RPCS: RPCDefinition[] = [ From ec7c64d4fc06aa08f2d2f267989fde2602705ef6 Mon Sep 17 00:00:00 2001 From: Matthew Walsh Date: Fri, 7 Jul 2023 09:05:58 +0100 Subject: [PATCH 003/172] Provide missing history property (#19896) --- ui/pages/confirm-signature-request/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/pages/confirm-signature-request/index.js b/ui/pages/confirm-signature-request/index.js index ef1a43a49..b86b23a6e 100644 --- a/ui/pages/confirm-signature-request/index.js +++ b/ui/pages/confirm-signature-request/index.js @@ -1,7 +1,7 @@ import PropTypes from 'prop-types'; import React, { useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { withRouter } from 'react-router-dom'; +import { useHistory, withRouter } from 'react-router-dom'; import log from 'loglevel'; import { cloneDeep } from 'lodash'; import * as actions from '../../store/actions'; @@ -69,6 +69,7 @@ const ConfirmTxScreen = ({ match }) => { ///: END:ONLY_INCLUDE_IN const [prevValue, setPrevValues] = useState(); + const history = useHistory(); useEffect(() => { const unconfTxList = txHelper( @@ -174,6 +175,7 @@ const ConfirmTxScreen = ({ match }) => { return ( Date: Wed, 5 Jul 2023 20:54:46 +0800 Subject: [PATCH 004/172] fix: fetch for snap registry (#19866) --- app/scripts/controllers/preferences.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 052f218a3..9be792c49 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -526,7 +526,8 @@ export default class PreferencesController { async updateSnapRegistry() { let snapRegistry; try { - snapRegistry = await fetch(KEYRING_SNAPS_REGISTRY_URL); + const response = await fetch(KEYRING_SNAPS_REGISTRY_URL); + snapRegistry = await response.json(); } catch (error) { console.error(`Failed to fetch registry: `, error); snapRegistry = {}; From cc9d87c365d10052aaf45452513e3f6bb008f84a Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 11 Jul 2023 18:27:52 -0230 Subject: [PATCH 005/172] Fix intermittent build error (#19966) Occasionally our builds have been failing with the error "Unexpected end of JSON input", with a stack pointing at `lavamoat-core`. The file in question was reading the policy, reading overrides, merging them, then writing the policy back to disk. The intermittent errors can be explained if the policy file was read in one process while it was being written in another. The extension build script builds bundles in multiple processes in parallel, so it does follow that this would happen some of the time. This could result in a partial policy file being read by the build script, resulting in a JSON parsing error. This has been fixed by removing the policy write step using a patch. We don't need this step. We update the policy using a different function altogether, and we have a CI job to ensure we never forget to update it. --- .../lavamoat-core-npm-14.2.0-c453f4f755.patch | 18 ++++++++++++++++++ lavamoat/build-system/policy.json | 1 - package.json | 3 ++- yarn.lock | 17 ++++++++++++++--- 4 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 .yarn/patches/lavamoat-core-npm-14.2.0-c453f4f755.patch diff --git a/.yarn/patches/lavamoat-core-npm-14.2.0-c453f4f755.patch b/.yarn/patches/lavamoat-core-npm-14.2.0-c453f4f755.patch new file mode 100644 index 000000000..abae9b295 --- /dev/null +++ b/.yarn/patches/lavamoat-core-npm-14.2.0-c453f4f755.patch @@ -0,0 +1,18 @@ +diff --git a/src/loadPolicy.js b/src/loadPolicy.js +index ef71923f9282d6a5e9f74e6ec6fa0516f28f508b..0118fda7e1b0fa461ec01ceff8d7112d072f3dfb 100644 +--- a/src/loadPolicy.js ++++ b/src/loadPolicy.js +@@ -33,10 +33,9 @@ async function loadPolicyAndApplyOverrides({ debugMode, policyPath, policyOverri + } + const policyOverride = await readPolicyFile({ debugMode, policyPath: policyOverridePath }) + lavamoatPolicy = mergePolicy(policy, policyOverride) +- // TODO: Only write if merge results in changes. +- // Would have to make a deep equal check on whole policy, which is a waste of time. +- // mergePolicy() should be able to do it in one pass. +- fs.writeFileSync(policyPath, jsonStringify(lavamoatPolicy, { space: 2 })) ++ // Skip policy write step to prevent intermittent build failures ++ // The extension validates the policy in a separate step, we don't need it ++ // to be written to disk here. + } + return lavamoatPolicy + } diff --git a/lavamoat/build-system/policy.json b/lavamoat/build-system/policy.json index a615563a8..4051645e9 100644 --- a/lavamoat/build-system/policy.json +++ b/lavamoat/build-system/policy.json @@ -6283,7 +6283,6 @@ "events": true, "fs.existsSync": true, "fs.readFileSync": true, - "fs.writeFileSync": true, "path.extname": true, "path.join": true }, diff --git a/package.json b/package.json index fdb303c67..b4ec6bc10 100644 --- a/package.json +++ b/package.json @@ -196,7 +196,8 @@ "request@^2.83.0": "patch:request@npm%3A2.88.2#./.yarn/patches/request-npm-2.88.2-f4a57c72c4.patch", "request@^2.88.2": "patch:request@npm%3A2.88.2#./.yarn/patches/request-npm-2.88.2-f4a57c72c4.patch", "request@^2.85.0": "patch:request@npm%3A2.88.2#./.yarn/patches/request-npm-2.88.2-f4a57c72c4.patch", - "@metamask/signature-controller@^4.0.1": "patch:@metamask/signature-controller@npm%3A4.0.1#./.yarn/patches/@metamask-signature-controller-npm-4.0.1-013e64c9fd.patch" + "@metamask/signature-controller@^4.0.1": "patch:@metamask/signature-controller@npm%3A4.0.1#./.yarn/patches/@metamask-signature-controller-npm-4.0.1-013e64c9fd.patch", + "lavamoat-core@^14.2.0": "patch:lavamoat-core@npm%3A14.2.0#./.yarn/patches/lavamoat-core-npm-14.2.0-c453f4f755.patch" }, "dependencies": { "@babel/runtime": "^7.18.9", diff --git a/yarn.lock b/yarn.lock index db6d24afd..6ecd9d1d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23184,6 +23184,17 @@ __metadata: languageName: node linkType: hard +"lavamoat-core@npm:14.2.0": + version: 14.2.0 + resolution: "lavamoat-core@npm:14.2.0" + dependencies: + json-stable-stringify: ^1.0.2 + lavamoat-tofu: ^6.0.2 + merge-deep: ^3.0.3 + checksum: 2f254c85a466561393a9ad0b8bcd8ff93b7b195d2f820f89be452348559f3fa689260887dcf4af3d605bc7ddb8fef2637ca7d5bfe1b7f565050aca172b9733d6 + languageName: node + linkType: hard + "lavamoat-core@npm:^10.0.1": version: 10.1.2 resolution: "lavamoat-core@npm:10.1.2" @@ -23197,14 +23208,14 @@ __metadata: languageName: node linkType: hard -"lavamoat-core@npm:^14.2.0": +"lavamoat-core@patch:lavamoat-core@npm%3A14.2.0#./.yarn/patches/lavamoat-core-npm-14.2.0-c453f4f755.patch::locator=metamask-crx%40workspace%3A.": version: 14.2.0 - resolution: "lavamoat-core@npm:14.2.0" + resolution: "lavamoat-core@patch:lavamoat-core@npm%3A14.2.0#./.yarn/patches/lavamoat-core-npm-14.2.0-c453f4f755.patch::version=14.2.0&hash=70a573&locator=metamask-crx%40workspace%3A." dependencies: json-stable-stringify: ^1.0.2 lavamoat-tofu: ^6.0.2 merge-deep: ^3.0.3 - checksum: 2f254c85a466561393a9ad0b8bcd8ff93b7b195d2f820f89be452348559f3fa689260887dcf4af3d605bc7ddb8fef2637ca7d5bfe1b7f565050aca172b9733d6 + checksum: 964ecb811357e2c77ed9e41c02f69d1925a7b20b917fd44f800186a274c70a25fa056d62056509014233a0b2b4dab78b271458947560dbe64d44c963e0ccdf65 languageName: node linkType: hard From 2fad10e0a3d3882c7391d3f3f4b89da70bb150a8 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 11 Jul 2023 18:43:22 -0230 Subject: [PATCH 006/172] Fix MMI policy generation (#19967) The command `yarn lavamoat:auto` will fail unless the environment variable `CONFIGURATION_SERVICE_URL` is set locally. Most contributors will have no reason to set this to anything. This has been fixed by assigning this variable a default value of an empty string, as the error suggests doing. --- builds.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builds.yml b/builds.yml index fe4d755d3..03470aa6a 100644 --- a/builds.yml +++ b/builds.yml @@ -89,7 +89,7 @@ buildTypes: - SEGMENT_WRITE_KEY_REF: SEGMENT_MMI_WRITE_KEY - SUPPORT_LINK: https://mmi-support.zendesk.com/hc/en-us - SUPPORT_REQUEST_LINK: https://mmi-support.zendesk.com/hc/en-us/requests/new - - MMI_CONFIGURATION_SERVICE_URL + - MMI_CONFIGURATION_SERVICE_URL: '' # For some reason, MMI uses this type of versioning # Leaving it on for backwards compatibility isPrerelease: true From 5736e670f75b48afde71d35f236643420f7c20e2 Mon Sep 17 00:00:00 2001 From: Vinicius Stevam <45455812+vinistevam@users.noreply.github.com> Date: Wed, 12 Jul 2023 09:29:54 +0100 Subject: [PATCH 007/172] Approval flow adding success and error pages (#19778) --- app/_locales/en/messages.json | 12 ++ app/scripts/metamask-controller.js | 6 + lavamoat/browserify/beta/policy.json | 3 + lavamoat/browserify/desktop/policy.json | 3 + lavamoat/browserify/flask/policy.json | 3 + lavamoat/browserify/main/policy.json | 3 + lavamoat/browserify/mmi/policy.json | 3 + package.json | 4 +- test/e2e/tests/switch-custom-network.spec.js | 2 +- .../safe-component-list.js | 16 +- .../__snapshots__/error.test.js.snap | 69 ++++++++ .../__snapshots__/success.test.js.snap | 60 +++++++ ui/pages/confirmation/templates/error.js | 94 +++++++++++ ui/pages/confirmation/templates/error.test.js | 66 ++++++++ ui/pages/confirmation/templates/index.js | 5 + ui/pages/confirmation/templates/success.js | 94 +++++++++++ .../confirmation/templates/success.test.js | 66 ++++++++ ui/pages/confirmation/util.test.ts | 60 +++++++ ui/pages/confirmation/util.ts | 150 ++++++++++++++++++ yarn.lock | 10 +- 20 files changed, 715 insertions(+), 14 deletions(-) create mode 100644 ui/pages/confirmation/templates/__snapshots__/error.test.js.snap create mode 100644 ui/pages/confirmation/templates/__snapshots__/success.test.js.snap create mode 100644 ui/pages/confirmation/templates/error.js create mode 100644 ui/pages/confirmation/templates/error.test.js create mode 100644 ui/pages/confirmation/templates/success.js create mode 100644 ui/pages/confirmation/templates/success.test.js create mode 100644 ui/pages/confirmation/util.test.ts create mode 100644 ui/pages/confirmation/util.ts diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 328441d1e..39d8216b7 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -3504,6 +3504,18 @@ "restoreUserDataDescription": { "message": "You can restore user settings containing preferences and account addresses from a previously backed up JSON file." }, + "resultPageError": { + "message": "Error" + }, + "resultPageErrorDefaultMessage": { + "message": "The operation failed." + }, + "resultPageSuccess": { + "message": "Success" + }, + "resultPageSuccessDefaultMessage": { + "message": "The operation completed successfully." + }, "retryTransaction": { "message": "Retry transaction" }, diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 66326a010..018e39aff 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -3963,6 +3963,12 @@ export default class MetamaskController extends EventEmitter { this.approvalController.setFlowLoadingText.bind( this.approvalController, ), + showApprovalSuccess: this.approvalController.success.bind( + this.approvalController, + ), + showApprovalError: this.approvalController.error.bind( + this.approvalController, + ), sendMetrics: this.metaMetricsController.trackEvent.bind( this.metaMetricsController, ), diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index f3373a420..24f626987 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -775,6 +775,9 @@ } }, "@metamask/approval-controller": { + "globals": { + "console.info": true + }, "packages": { "@metamask/approval-controller>nanoid": true, "@metamask/base-controller": true, diff --git a/lavamoat/browserify/desktop/policy.json b/lavamoat/browserify/desktop/policy.json index e9b8572ae..1ff496ed2 100644 --- a/lavamoat/browserify/desktop/policy.json +++ b/lavamoat/browserify/desktop/policy.json @@ -775,6 +775,9 @@ } }, "@metamask/approval-controller": { + "globals": { + "console.info": true + }, "packages": { "@metamask/approval-controller>nanoid": true, "@metamask/base-controller": true, diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index e9b8572ae..1ff496ed2 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -775,6 +775,9 @@ } }, "@metamask/approval-controller": { + "globals": { + "console.info": true + }, "packages": { "@metamask/approval-controller>nanoid": true, "@metamask/base-controller": true, diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index f3373a420..24f626987 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -775,6 +775,9 @@ } }, "@metamask/approval-controller": { + "globals": { + "console.info": true + }, "packages": { "@metamask/approval-controller>nanoid": true, "@metamask/base-controller": true, diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index a097c6d55..46ea1ba04 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -996,6 +996,9 @@ } }, "@metamask/approval-controller": { + "globals": { + "console.info": true + }, "packages": { "@metamask/approval-controller>nanoid": true, "@metamask/base-controller": true, diff --git a/package.json b/package.json index b4ec6bc10..88754b540 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "resolutions": { "@babel/core": "patch:@babel/core@npm%3A7.21.5#./.yarn/patches/@babel-core-npm-7.21.5-c72c337956.patch", "@babel/runtime": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch", - "@metamask/approval-controller": "^3.3.0", + "@metamask/approval-controller": "^3.4.0", "@types/react": "^16.9.53", "analytics-node/axios": "^0.21.2", "ganache-core/lodash": "^4.17.21", @@ -226,7 +226,7 @@ "@metamask-institutional/transaction-update": "^0.1.21", "@metamask/address-book-controller": "^3.0.0", "@metamask/announcement-controller": "^4.0.0", - "@metamask/approval-controller": "^3.3.0", + "@metamask/approval-controller": "^3.4.0", "@metamask/assets-controllers": "^9.2.0", "@metamask/base-controller": "^3.0.0", "@metamask/browser-passworder": "^4.1.0", diff --git a/test/e2e/tests/switch-custom-network.spec.js b/test/e2e/tests/switch-custom-network.spec.js index 9e0cf6857..67c3ad1fc 100644 --- a/test/e2e/tests/switch-custom-network.spec.js +++ b/test/e2e/tests/switch-custom-network.spec.js @@ -2,7 +2,7 @@ const { strict: assert } = require('assert'); const FixtureBuilder = require('../fixture-builder'); const { convertToHexValue, withFixtures, openDapp } = require('../helpers'); -describe('Swtich ethereum chain', function () { +describe('Switch ethereum chain', function () { const ganacheOptions = { accounts: [ { diff --git a/ui/components/app/metamask-template-renderer/safe-component-list.js b/ui/components/app/metamask-template-renderer/safe-component-list.js index f8ae5650e..68101cfb3 100644 --- a/ui/components/app/metamask-template-renderer/safe-component-list.js +++ b/ui/components/app/metamask-template-renderer/safe-component-list.js @@ -12,6 +12,8 @@ import TextField from '../../ui/text-field'; import ConfirmationNetworkSwitch from '../../../pages/confirmation/components/confirmation-network-switch'; import UrlIcon from '../../ui/url-icon'; import Tooltip from '../../ui/tooltip/tooltip'; +import { AvatarIcon } from '../../component-library'; +import ActionableMessage from '../../ui/actionable-message/actionable-message'; ///: BEGIN:ONLY_INCLUDE_IN(snaps) import { SnapDelineator } from '../snaps/snap-delineator'; import { Copyable } from '../snaps/copyable'; @@ -21,19 +23,21 @@ import { SnapUIMarkdown } from '../snaps/snap-ui-markdown'; export const safeComponentList = { a: 'a', + ActionableMessage, + AvatarIcon, b: 'b', - i: 'i', - p: 'p', - div: 'div', - span: 'span', Box, Button, Chip, ConfirmationNetworkSwitch, DefinitionList, + div: 'div', + i: 'i', MetaMaskTranslation, NetworkDisplay, + p: 'p', Popover, + span: 'span', TextArea, TextField, Tooltip, @@ -41,9 +45,9 @@ export const safeComponentList = { Typography, UrlIcon, ///: BEGIN:ONLY_INCLUDE_IN(snaps) - SnapDelineator, Copyable, - Spinner, + SnapDelineator, SnapUIMarkdown, + Spinner, ///: END:ONLY_INCLUDE_IN }; diff --git a/ui/pages/confirmation/templates/__snapshots__/error.test.js.snap b/ui/pages/confirmation/templates/__snapshots__/error.test.js.snap new file mode 100644 index 000000000..30d96b667 --- /dev/null +++ b/ui/pages/confirmation/templates/__snapshots__/error.test.js.snap @@ -0,0 +1,69 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`error template matches the snapshot 1`] = ` +
+
+
+
+

+ Error mock +

+
+
+ +
+

+ Error +

+
+
+ +
+ The operation failed. +
+
+
+
+
+
+ +
+
+`; diff --git a/ui/pages/confirmation/templates/__snapshots__/success.test.js.snap b/ui/pages/confirmation/templates/__snapshots__/success.test.js.snap new file mode 100644 index 000000000..2c473b06d --- /dev/null +++ b/ui/pages/confirmation/templates/__snapshots__/success.test.js.snap @@ -0,0 +1,60 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`success template matches the snapshot 1`] = ` +
+
+
+
+

+ Success mock +

+
+
+ +
+

+ Success +

+
+ Success message +
+
+
+
+ +
+
+`; diff --git a/ui/pages/confirmation/templates/error.js b/ui/pages/confirmation/templates/error.js new file mode 100644 index 000000000..d0c41acfe --- /dev/null +++ b/ui/pages/confirmation/templates/error.js @@ -0,0 +1,94 @@ +import { IconName, IconSize } from '../../../components/component-library'; +import { + FontWeight, + TextAlign, + BlockSize, + AlignItems, + FlexDirection, + JustifyContent, + TypographyVariant, + IconColor, + BackgroundColor, +} from '../../../helpers/constants/design-system'; +import { processError } from '../util'; + +function getValues(pendingApproval, t, actions, _history) { + return { + content: [ + { + key: 'header', + element: 'Box', + props: { + flexDirection: FlexDirection.Column, + alignItems: AlignItems.center, + height: BlockSize.Full, + padding: 4, + }, + children: [ + ...(pendingApproval.requestData.header || []), + { + key: 'content', + element: 'Box', + props: { + flexDirection: FlexDirection.Column, + alignItems: AlignItems.center, + justifyContent: JustifyContent.center, + height: BlockSize.Full, + paddingTop: 2, + paddingBottom: 2, + }, + children: [ + { + key: 'icon', + element: 'AvatarIcon', + props: { + iconName: IconName.Warning, + size: IconSize.Xl, + iconProps: { size: IconSize.Xl }, + color: IconColor.errorDefault, + backgroundColor: BackgroundColor.errorMuted, + }, + children: 'Icon', + }, + { + key: 'heading', + element: 'Typography', + props: { + variant: TypographyVariant.H3, + fontWeight: FontWeight.Bold, + paddingBottom: 2, + }, + children: t('resultPageError'), + }, + { + key: 'message', + element: 'Box', + props: { + alignItems: AlignItems.center, + textAlign: TextAlign.Center, + }, + children: processError( + pendingApproval.requestData.error, + t('resultPageErrorDefaultMessage'), + ), + }, + ], + }, + ], + }, + ], + submitText: t('ok'), + onSubmit: () => + actions.resolvePendingApproval( + pendingApproval.id, + pendingApproval.requestData, + ), + networkDisplay: false, + }; +} + +const error = { + getValues, +}; + +export default error; diff --git a/ui/pages/confirmation/templates/error.test.js b/ui/pages/confirmation/templates/error.test.js new file mode 100644 index 000000000..3c726eb0b --- /dev/null +++ b/ui/pages/confirmation/templates/error.test.js @@ -0,0 +1,66 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { waitFor } from '@testing-library/react'; + +import { ApprovalType } from '@metamask/controller-utils'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import Confirmation from '../confirmation'; + +jest.mock('../../../../shared/lib/fetch-with-cache'); + +const middleware = [thunk]; +const mockApprovalId = 1; +const mockApproval = { + id: mockApprovalId, + origin: 'https://test-dapp.metamask.io', + requestData: { + header: [ + { + key: 'headerText', + element: 'Typography', + children: 'Error mock', + props: { + variant: 'h2', + class: 'header-mock-class', + }, + }, + ], + message: 'Error message', + }, +}; + +const mockBaseStore = { + metamask: { + pendingApprovals: { + [mockApprovalId]: mockApproval, + }, + approvalFlows: [], + subjectMetadata: {}, + }, +}; + +describe('error template', () => { + it('matches the snapshot', async () => { + const testStore = { + metamask: { + ...mockBaseStore.metamask, + pendingApprovals: { + [mockApprovalId]: { + ...mockApproval, + type: ApprovalType.ResultError, + }, + }, + }, + }; + const store = configureMockStore(middleware)(testStore); + const { getByText, container } = renderWithProvider( + , + store, + ); + await waitFor(() => { + expect(getByText('Error mock')).toBeInTheDocument(); + expect(container).toMatchSnapshot(); + }); + }); +}); diff --git a/ui/pages/confirmation/templates/index.js b/ui/pages/confirmation/templates/index.js index 36f1e8e05..5839ae47c 100644 --- a/ui/pages/confirmation/templates/index.js +++ b/ui/pages/confirmation/templates/index.js @@ -8,6 +8,8 @@ import { } from '../../../store/actions'; import addEthereumChain from './add-ethereum-chain'; import switchEthereumChain from './switch-ethereum-chain'; +import success from './success'; +import error from './error'; ///: BEGIN:ONLY_INCLUDE_IN(snaps) import snapAlert from './snaps/snap-alert/snap-alert'; import snapConfirmation from './snaps/snap-confirmation/snap-confirmation'; @@ -17,6 +19,9 @@ import snapPrompt from './snaps/snap-prompt/snap-prompt'; const APPROVAL_TEMPLATES = { [ApprovalType.AddEthereumChain]: addEthereumChain, [ApprovalType.SwitchEthereumChain]: switchEthereumChain, + // Use ApprovalType from utils controller + [ApprovalType.ResultSuccess]: success, + [ApprovalType.ResultError]: error, ///: BEGIN:ONLY_INCLUDE_IN(snaps) [ApprovalType.SnapDialogAlert]: snapAlert, [ApprovalType.SnapDialogConfirmation]: snapConfirmation, diff --git a/ui/pages/confirmation/templates/success.js b/ui/pages/confirmation/templates/success.js new file mode 100644 index 000000000..3d324642b --- /dev/null +++ b/ui/pages/confirmation/templates/success.js @@ -0,0 +1,94 @@ +import { IconName, IconSize } from '../../../components/component-library'; +import { + FontWeight, + BlockSize, + AlignItems, + FlexDirection, + JustifyContent, + TypographyVariant, + TextAlign, + IconColor, + BackgroundColor, +} from '../../../helpers/constants/design-system'; +import { processString } from '../util'; + +function getValues(pendingApproval, t, actions, _history) { + return { + content: [ + { + key: 'header', + element: 'Box', + props: { + flexDirection: FlexDirection.Column, + alignItems: AlignItems.center, + height: BlockSize.Full, + padding: 4, + }, + children: [ + ...(pendingApproval.requestData.header || []), + { + key: 'content', + element: 'Box', + props: { + flexDirection: FlexDirection.Column, + alignItems: AlignItems.center, + justifyContent: JustifyContent.center, + height: BlockSize.Full, + paddingTop: 2, + paddingBottom: 2, + }, + children: [ + { + key: 'icon', + element: 'AvatarIcon', + props: { + iconName: IconName.Confirmation, + size: IconSize.Xl, + iconProps: { size: IconSize.Xl }, + color: IconColor.successDefault, + backgroundColor: BackgroundColor.successMuted, + }, + children: 'Icon', + }, + { + key: 'heading', + element: 'Typography', + props: { + variant: TypographyVariant.H3, + fontWeight: FontWeight.Bold, + paddingBottom: 2, + }, + children: t('resultPageSuccess'), + }, + { + key: 'message', + element: 'Box', + props: { + alignItems: AlignItems.center, + textAlign: TextAlign.Center, + }, + children: processString( + pendingApproval.requestData.message, + t('resultPageSuccessDefaultMessage'), + ), + }, + ], + }, + ], + }, + ], + submitText: t('ok'), + onSubmit: () => + actions.resolvePendingApproval( + pendingApproval.id, + pendingApproval.requestData, + ), + networkDisplay: false, + }; +} + +const success = { + getValues, +}; + +export default success; diff --git a/ui/pages/confirmation/templates/success.test.js b/ui/pages/confirmation/templates/success.test.js new file mode 100644 index 000000000..b3c22d33e --- /dev/null +++ b/ui/pages/confirmation/templates/success.test.js @@ -0,0 +1,66 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { waitFor } from '@testing-library/react'; + +import { ApprovalType } from '@metamask/controller-utils'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import Confirmation from '../confirmation'; + +jest.mock('../../../../shared/lib/fetch-with-cache'); + +const middleware = [thunk]; +const mockApprovalId = 1; +const mockApproval = { + id: mockApprovalId, + origin: 'https://test-dapp.metamask.io', + requestData: { + header: [ + { + key: 'headerText', + element: 'Typography', + children: 'Success mock', + props: { + variant: 'h2', + class: 'header-mock-class', + }, + }, + ], + message: 'Success message', + }, +}; + +const mockBaseStore = { + metamask: { + pendingApprovals: { + [mockApprovalId]: mockApproval, + }, + approvalFlows: [], + subjectMetadata: {}, + }, +}; + +describe('success template', () => { + it('matches the snapshot', async () => { + const testStore = { + metamask: { + ...mockBaseStore.metamask, + pendingApprovals: { + [mockApprovalId]: { + ...mockApproval, + type: ApprovalType.ResultSuccess, + }, + }, + }, + }; + const store = configureMockStore(middleware)(testStore); + const { getByText, container } = renderWithProvider( + , + store, + ); + await waitFor(() => { + expect(getByText('Success mock')).toBeInTheDocument(); + expect(container).toMatchSnapshot(); + }); + }); +}); diff --git a/ui/pages/confirmation/util.test.ts b/ui/pages/confirmation/util.test.ts new file mode 100644 index 000000000..7a0e85efa --- /dev/null +++ b/ui/pages/confirmation/util.test.ts @@ -0,0 +1,60 @@ +import { ResultComponent } from '@metamask/approval-controller'; +import { processError, processString } from './util'; + +const FALLBACK_MESSAGE = 'Fallback Message'; +const mockResultComponent: ResultComponent = { + key: 'mock-key', + name: 'mock-component', + properties: { message: 'mock1', message2: 'mock2' }, + children: 'Mock child', +}; + +const expectedTemplateRendererComponent = { + key: 'mock-key', + props: { + message: 'mock1', + message2: 'mock2', + }, + children: 'Mock child', + element: 'mock-component', +}; + +describe('processError', () => { + it('returns TemplateRendererComponent when input is not defined', () => { + const result = processError(undefined, FALLBACK_MESSAGE); + expect(result).toEqual({ + key: 'error', + element: 'ActionableMessage', + props: { type: 'danger', message: FALLBACK_MESSAGE }, + }); + }); + + it('returns TemplateRendererComponent when input is a string', () => { + const result = processError('Error Message', FALLBACK_MESSAGE); + expect(result).toEqual({ + key: 'error', + element: 'ActionableMessage', + props: { type: 'danger', message: 'Error Message' }, + }); + }); + it('returns TemplateRendererComponent when input is a ResultComponent', () => { + const result = processError(mockResultComponent, FALLBACK_MESSAGE); + expect(result).toEqual(expectedTemplateRendererComponent); + }); +}); + +describe('processString', () => { + it('returns string when input is not defined', () => { + const result = processString(undefined, FALLBACK_MESSAGE); + expect(result[0]).toEqual(FALLBACK_MESSAGE); + }); + + it('returns TemplateRendererComponent when input is a string', () => { + const result = processString('Hello', FALLBACK_MESSAGE); + expect(result).toEqual(['Hello']); + }); + it('returns TemplateRendererComponent when input is a ResultComponent', () => { + const result = processString(mockResultComponent, FALLBACK_MESSAGE); + expect(result).toEqual(expectedTemplateRendererComponent); + }); +}); diff --git a/ui/pages/confirmation/util.ts b/ui/pages/confirmation/util.ts new file mode 100644 index 000000000..ca75ee665 --- /dev/null +++ b/ui/pages/confirmation/util.ts @@ -0,0 +1,150 @@ +import { ResultComponent } from '@metamask/approval-controller'; + +type TemplateRendererComponent = { + key: string; + element: string; + props?: Record; + children?: + | string + | TemplateRendererComponent + | (string | TemplateRendererComponent)[]; +}; + +/** + * Processes an error message or ResultComponent and returns a TemplateRendererComponent + * or an array of strings | TemplateRendererComponents. + * + * @param input - The message or component to process. + * @param fallback - The fallback message to use when the input is not valid. + * @returns The processed error component. + */ +export function processError( + input: undefined | string | ResultComponent | ResultComponent[], + fallback: string, +): TemplateRendererComponent | (string | TemplateRendererComponent)[] { + const currentInput = convertResultComponents(input) || fallback; + + if (typeof currentInput !== 'string') { + return currentInput; + } + + return { + key: 'error', + element: 'ActionableMessage', + props: { type: 'danger', message: currentInput }, + }; +} + +/** + * Processes a string or ResultComponent and returns a string or TemplateRendererComponent + * or an array of strings | TemplateRendererComponents. + * + * @param input - The message or component to process. + * @param fallback - The fallback string to use when the input is not valid. + * @returns The processed message. + */ +export function processString( + input: undefined | string | ResultComponent | ResultComponent[], + fallback: string, +): string | TemplateRendererComponent | (string | TemplateRendererComponent)[] { + const currentInput = convertResultComponents(input) || fallback; + + if (typeof currentInput !== 'string') { + return currentInput; + } + + return applyBold(currentInput); +} + +/** + * Applies bold formatting to the message. + * + * @param message - The input message to apply bold formatting to. + * @returns The formatted message. + */ +function applyBold(message: string): (string | TemplateRendererComponent)[] { + const boldPattern = /\*\*(.+?)\*\*/gu; + + return findMarkdown(message, boldPattern, (formattedText, index) => ({ + key: `bold-${index}`, + element: 'b', + children: formattedText, + })); +} + +/** + * Finds and formats markdown elements in the given text. + * + * @param text - The input text to search for markdown elements. + * @param pattern - The pattern to match the markdown elements. + * @param getElement - The callback function to create the formatted elements. + * @returns The array of formatted elements. + */ +function findMarkdown( + text: string, + pattern: RegExp, + getElement: ( + formattedText: string, + index: number, + ) => TemplateRendererComponent, +): (string | TemplateRendererComponent)[] { + let position = 0; + let index = 0; + + const matches = Array.from(text.matchAll(pattern)); + const elements = []; + + for (const match of matches) { + const rawText = text.substring(position, match.index); + + if (rawText.length) { + elements.push(rawText); + } + + const formattedText = match[1]; + const formattedElement = getElement(formattedText, index); + + elements.push(formattedElement); + + position = (match.index as number) + match[0].length; + index += 1; + } + + const finalRawText = text.substring(position); + + if (finalRawText.length) { + elements.push(finalRawText); + } + + return elements; +} + +function convertResultComponents( + input: undefined | string | ResultComponent | (string | ResultComponent)[], +): + | undefined + | string + | TemplateRendererComponent + | (string | TemplateRendererComponent)[] { + if (input === undefined) { + return undefined; + } + + if (typeof input === 'string') { + return input; + } + + if (Array.isArray(input)) { + return input.map(convertResultComponents) as ( + | string + | TemplateRendererComponent + )[]; + } + + return { + key: input.key, + element: input.name, + props: input.properties, + children: convertResultComponents(input.children), + }; +} diff --git a/yarn.lock b/yarn.lock index 6ecd9d1d5..70031d4d3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3857,16 +3857,16 @@ __metadata: languageName: node linkType: hard -"@metamask/approval-controller@npm:^3.3.0": - version: 3.3.0 - resolution: "@metamask/approval-controller@npm:3.3.0" +"@metamask/approval-controller@npm:^3.4.0": + version: 3.4.0 + resolution: "@metamask/approval-controller@npm:3.4.0" dependencies: "@metamask/base-controller": ^3.0.0 "@metamask/utils": ^5.0.2 eth-rpc-errors: ^4.0.2 immer: ^9.0.6 nanoid: ^3.1.31 - checksum: 1fa6111a897d6f4aa369fd1a669fb5e16558277019f9d6c61449aea0d7b2672a62c189e5b3d9e84ab6e4d5826932c78d2bdb0f05aafb184a4ff07903c46abf2c + checksum: 153136800fbd8cd50e2d6012740526c55e74e3f8e5aa99a05d5788e8bae04ede622608a1adf67dcf0986162e9e7d1d11b6f6f0df438904b65db7435b881c2e3f languageName: node linkType: hard @@ -24596,7 +24596,7 @@ __metadata: "@metamask-institutional/transaction-update": ^0.1.21 "@metamask/address-book-controller": ^3.0.0 "@metamask/announcement-controller": ^4.0.0 - "@metamask/approval-controller": ^3.3.0 + "@metamask/approval-controller": ^3.4.0 "@metamask/assets-controllers": ^9.2.0 "@metamask/auto-changelog": ^2.1.0 "@metamask/base-controller": ^3.0.0 From 1ea934165b5d19f4261e31dc867bb05a6090976d Mon Sep 17 00:00:00 2001 From: Nidhi Kumari Date: Wed, 12 Jul 2023 17:03:58 +0530 Subject: [PATCH 008/172] Show product tour only on home page (#19938) * show product tour only on home page * updated variable name --------- Co-authored-by: David Walsh --- ui/components/multichain/app-header/app-header.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/components/multichain/app-header/app-header.js b/ui/components/multichain/app-header/app-header.js index d6c9e81b6..1ee4e2fa4 100644 --- a/ui/components/multichain/app-header/app-header.js +++ b/ui/components/multichain/app-header/app-header.js @@ -68,6 +68,7 @@ export const AppHeader = ({ location }) => { const menuRef = useRef(false); const origin = useSelector(getOriginOfCurrentTab); const history = useHistory(); + const isHomePage = location.pathname === DEFAULT_ROUTE; const isUnlocked = useSelector((state) => state.metamask.isUnlocked); const t = useI18nContext(); const chainId = useSelector(getCurrentChainId); @@ -241,6 +242,7 @@ export const AppHeader = ({ location }) => { )} {showProductTour && popupStatus && + isHomePage && multichainProductTourStep === 1 ? ( Date: Wed, 12 Jul 2023 12:01:49 +0000 Subject: [PATCH 009/172] builds/mmi: Set default value for `MMI_CONFIGURATION_SERVICE_URL` to production endpoint (#19955) * builds: set MMI_CONFIGURATION_SERVICE_URL default to prod endpoint (rf #19899) * development/build: add MMI_CONFIGURATION_SERVICE_URL to required prod parameters --- builds.yml | 2 +- development/build/config.js | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/builds.yml b/builds.yml index 03470aa6a..99311a32d 100644 --- a/builds.yml +++ b/builds.yml @@ -87,9 +87,9 @@ buildTypes: - SEGMENT_MMI_WRITE_KEY - INFURA_ENV_KEY_REF: INFURA_MMI_PROJECT_ID - SEGMENT_WRITE_KEY_REF: SEGMENT_MMI_WRITE_KEY + - MMI_CONFIGURATION_SERVICE_URL: https://configuration.metamask-institutional.io/v1/configuration/default - SUPPORT_LINK: https://mmi-support.zendesk.com/hc/en-us - SUPPORT_REQUEST_LINK: https://mmi-support.zendesk.com/hc/en-us/requests/new - - MMI_CONFIGURATION_SERVICE_URL: '' # For some reason, MMI uses this type of versioning # Leaving it on for backwards compatibility isPrerelease: true diff --git a/development/build/config.js b/development/build/config.js index 0eee28ce3..4e4ee1ea9 100644 --- a/development/build/config.js +++ b/development/build/config.js @@ -11,7 +11,12 @@ const VARIABLES_REQUIRED_IN_PRODUCTION = { main: ['INFURA_PROD_PROJECT_ID', 'SEGMENT_PROD_WRITE_KEY', 'SENTRY_DSN'], beta: ['INFURA_BETA_PROJECT_ID', 'SEGMENT_BETA_WRITE_KEY', 'SENTRY_DSN'], flask: ['INFURA_FLASK_PROJECT_ID', 'SEGMENT_FLASK_WRITE_KEY', 'SENTRY_DSN'], - mmi: ['INFURA_MMI_PROJECT_ID', 'SEGMENT_MMI_WRITE_KEY', 'SENTRY_DSN'], + mmi: [ + 'INFURA_MMI_PROJECT_ID', + 'MMI_CONFIGURATION_SERVICE_URL', + 'SEGMENT_MMI_WRITE_KEY', + 'SENTRY_DSN', + ], }; async function fromIniFile(filepath) { From 177ea83f20d1e6557865e611293ce934450a252b Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 12 Jul 2023 10:17:14 -0230 Subject: [PATCH 010/172] Replace deprecated install command (#19968) The `--frozen-lockfile` flag is not supported by Yarn v3. It has been replaced by the Yarn v3 equivalent, which is `--immutable`. Additionally, the `deps-install` script was deleted and this command was inlined in the CircleCI configuration. I don't think we need to maintain a separate script just for one command. --- .circleci/config.yml | 3 +-- .circleci/scripts/deps-install.sh | 9 --------- 2 files changed, 1 insertion(+), 11 deletions(-) delete mode 100755 .circleci/scripts/deps-install.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index 496486a16..a8522d1ad 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -363,8 +363,7 @@ jobs: fi - run: name: Install deps - command: | - .circleci/scripts/deps-install.sh + command: yarn --immutable - save_cache: key: dependency-cache-v1-{{ checksum "yarn.lock" }} paths: diff --git a/.circleci/scripts/deps-install.sh b/.circleci/scripts/deps-install.sh deleted file mode 100755 index ddcf2cf8c..000000000 --- a/.circleci/scripts/deps-install.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -# Print commands and their arguments as they are executed. -set -x -# Exit immediately if a command exits with a non-zero status. -set -e - -yarn install --frozen-lockfile - From 73a203f1067390b95c50c79150aa35a5f5b8f749 Mon Sep 17 00:00:00 2001 From: Jyoti Puri Date: Wed, 12 Jul 2023 19:50:55 +0530 Subject: [PATCH 011/172] Integrating ppom-validator with extension (#19511) --- app/manifest/v2/chrome.json | 2 +- app/scripts/lib/indexed-db-backend.test.ts | 93 +++++++++++++++ app/scripts/lib/indexed-db-backend.ts | 127 +++++++++++++++++++++ app/scripts/metamask-controller.js | 32 ++++++ builds.yml | 1 + development/build/static.js | 23 +++- package.json | 2 + yarn.lock | 105 ++++++++++++++++- 8 files changed, 374 insertions(+), 11 deletions(-) create mode 100644 app/scripts/lib/indexed-db-backend.test.ts create mode 100644 app/scripts/lib/indexed-db-backend.ts diff --git a/app/manifest/v2/chrome.json b/app/manifest/v2/chrome.json index a152130d8..10de9fdf6 100644 --- a/app/manifest/v2/chrome.json +++ b/app/manifest/v2/chrome.json @@ -1,5 +1,5 @@ { - "content_security_policy": "frame-ancestors 'none'; script-src 'self'; object-src 'self'", + "content_security_policy": "frame-ancestors 'none'; script-src 'self' 'wasm-unsafe-eval'; object-src 'self'", "externally_connectable": { "matches": ["https://metamask.io/*"], "ids": ["*"] diff --git a/app/scripts/lib/indexed-db-backend.test.ts b/app/scripts/lib/indexed-db-backend.test.ts new file mode 100644 index 000000000..3aca51959 --- /dev/null +++ b/app/scripts/lib/indexed-db-backend.test.ts @@ -0,0 +1,93 @@ +import 'fake-indexeddb/auto'; + +import { IndexedDBPPOMStorage } from './indexed-db-backend'; + +Object.defineProperty(globalThis, 'crypto', { + value: { + subtle: { + digest: () => new ArrayBuffer(12), + }, + }, +}); + +const enc = new TextEncoder(); +const dec = new TextDecoder('utf-8'); + +describe('IndexedDBPPOMStorage', () => { + it('should be able to initialise correctly', () => { + const indexDBBackend = new IndexedDBPPOMStorage('PPOMDB', 1); + expect(indexDBBackend).toBeDefined(); + }); + + it('should be able to write and read file data if checksum matches', async () => { + const indexDBBackend = new IndexedDBPPOMStorage('PPOMDB', 1); + await indexDBBackend.write( + { name: 'fake_name', chainId: '5' }, + enc.encode('fake_data'), + '000000000000000000000000', + ); + const file = await indexDBBackend.read( + { name: 'fake_name', chainId: '5' }, + '000000000000000000000000', + ); + expect(dec.decode(file)).toStrictEqual('fake_data'); + }); + + it('should fail to write if checksum does not match', async () => { + const indexDBBackend = new IndexedDBPPOMStorage('PPOMDB', 1); + await expect(async () => { + await indexDBBackend.write( + { name: 'fake_name', chainId: '5' }, + enc.encode('fake_data'), + 'XXX', + ); + }).rejects.toThrow('Checksum mismatch'); + }); + + it('should fail to read if checksum does not match', async () => { + const indexDBBackend = new IndexedDBPPOMStorage('PPOMDB', 1); + await expect(async () => { + await indexDBBackend.write( + { name: 'fake_name', chainId: '5' }, + enc.encode('fake_data'), + '000000000000000000000000', + ); + await indexDBBackend.read({ name: 'fake_name', chainId: '5' }, 'XXX'); + }).rejects.toThrow('Checksum mismatch'); + }); + + it('should delete a file when delete method is called', async () => { + const indexDBBackend = new IndexedDBPPOMStorage('PPOMDB', 1); + await indexDBBackend.write( + { name: 'fake_name', chainId: '5' }, + enc.encode('fake_data'), + '000000000000000000000000', + ); + await indexDBBackend.delete({ name: 'fake_name', chainId: '5' }); + const result = await indexDBBackend.read( + { name: 'fake_name', chainId: '5' }, + '000000000000000000000000', + ); + expect(result).toBeUndefined(); + }); + + it('should list all keys when dir is called', async () => { + const keys = [ + { chainId: '5', name: 'fake_name_1' }, + { chainId: '1', name: 'fake_name_2' }, + ]; + const indexDBBackend = new IndexedDBPPOMStorage('PPOMDB', 1); + await indexDBBackend.write( + keys[0], + enc.encode('fake_data_1'), + '000000000000000000000000', + ); + await indexDBBackend.write( + keys[1], + enc.encode('fake_data_2'), + '000000000000000000000000', + ); + const result = await indexDBBackend.dir(); + expect(result).toStrictEqual(keys); + }); +}); diff --git a/app/scripts/lib/indexed-db-backend.ts b/app/scripts/lib/indexed-db-backend.ts new file mode 100644 index 000000000..41c5af262 --- /dev/null +++ b/app/scripts/lib/indexed-db-backend.ts @@ -0,0 +1,127 @@ +import { StorageBackend } from '@metamask/ppom-validator'; + +type StorageKey = { + name: string; + chainId: string; +}; + +const validateChecksum = async ( + key: StorageKey, + data: ArrayBuffer, + checksum: string, +) => { + const hash = await crypto.subtle.digest('SHA-256', data); + const hashString = Array.from(new Uint8Array(hash)) + .map((b) => b.toString(16).padStart(2, '0')) + .join(''); + + if (hashString !== checksum) { + throw new Error(`Checksum mismatch for key ${key}`); + } +}; + +export class IndexedDBPPOMStorage implements StorageBackend { + private storeName: string; + + private dbVersion: number; + + constructor(storeName: string, dbVersion: number) { + this.storeName = storeName; + this.dbVersion = dbVersion; + } + + #getObjectStore(mode: IDBTransactionMode): Promise { + return new Promise((resolve, reject) => { + const request = indexedDB.open(this.storeName, this.dbVersion); + + request.onerror = (event: Event) => { + reject( + new Error( + `Failed to open database ${this.storeName}: ${ + (event.target as any)?.error + }`, + ), + ); + }; + + request.onupgradeneeded = (event) => { + const db = (event.target as IDBOpenDBRequest).result; + + if (!db.objectStoreNames.contains(this.storeName)) { + db.createObjectStore(this.storeName, { + keyPath: ['name', 'chainId'], + }); + } + }; + + request.onsuccess = (event) => { + const db = (event.target as IDBOpenDBRequest).result; + const transaction = db.transaction([this.storeName], mode); + const objectStore = transaction.objectStore(this.storeName); + resolve(objectStore); + }; + }); + } + + private async objectStoreAction( + method: 'get' | 'delete' | 'put' | 'getAllKeys', + args?: any, + mode: IDBTransactionMode = 'readonly', + ): Promise { + return new Promise((resolve, reject) => { + this.#getObjectStore(mode) + .then((objectStore) => { + const request = objectStore[method](args); + + request.onsuccess = async (event) => { + resolve(event); + }; + + request.onerror = (event) => { + reject( + new Error( + `Error in indexDB operation ${method}: ${ + (event.target as any)?.error + }`, + ), + ); + }; + }) + .catch((error) => { + reject(error); + }); + }); + } + + async read(key: StorageKey, checksum: string): Promise { + const event = await this.objectStoreAction('get', [key.name, key.chainId]); + const data = (event.target as any)?.result?.data; + await validateChecksum(key, data, checksum); + return data; + } + + async write( + key: StorageKey, + data: ArrayBuffer, + checksum: string, + ): Promise { + await validateChecksum(key, data, checksum); + await this.objectStoreAction('put', { ...key, data }, 'readwrite'); + } + + async delete(key: StorageKey): Promise { + await this.objectStoreAction( + 'delete', + [key.name, key.chainId], + 'readwrite', + ); + } + + async dir(): Promise { + const event = await this.objectStoreAction('getAllKeys'); + return (event.target as any)?.result.map(([name, chainId]: string[]) => ({ + name, + chainId, + })); + } +} diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 018e39aff..17b8d98dd 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -76,6 +76,9 @@ import { CustodyController } from '@metamask-institutional/custody-controller'; import { TransactionUpdateController } from '@metamask-institutional/transaction-update'; ///: END:ONLY_INCLUDE_IN import { SignatureController } from '@metamask/signature-controller'; +///: BEGIN:ONLY_INCLUDE_IN(blockaid) +import { PPOMController, createPPOMMiddleware } from '@metamask/ppom-validator'; +///: END:ONLY_INCLUDE_IN ///: BEGIN:ONLY_INCLUDE_IN(desktop) // eslint-disable-next-line import/order @@ -210,6 +213,9 @@ import { } from './controllers/permissions'; import createRPCMethodTrackingMiddleware from './lib/createRPCMethodTrackingMiddleware'; import { securityProviderCheck } from './lib/security-provider-helpers'; +///: BEGIN:ONLY_INCLUDE_IN(blockaid) +import { IndexedDBPPOMStorage } from './lib/indexed-db-backend'; +///: END:ONLY_INCLUDE_IN import { updateCurrentLocale } from './translate'; export const METAMASK_CONTROLLER_EVENTS = { @@ -630,6 +636,22 @@ export default class MetamaskController extends EventEmitter { this.phishingController.setStalelistRefreshInterval(30 * SECOND); } + ///: BEGIN:ONLY_INCLUDE_IN(blockaid) + this.ppomController = new PPOMController({ + messenger: this.controllerMessenger.getRestricted({ + name: 'PPOMController', + }), + storageBackend: new IndexedDBPPOMStorage('PPOMDB', 1), + provider: this.provider, + state: initState.PPOMController, + chainId: this.networkController.state.providerConfig.chainId, + onNetworkChange: networkControllerMessenger.subscribe.bind( + networkControllerMessenger, + 'NetworkController:stateChange', + ), + }); + ///: END:ONLY_INCLUDE_IN + const announcementMessenger = this.controllerMessenger.getRestricted({ name: 'AnnouncementController', }); @@ -1529,6 +1551,9 @@ export default class MetamaskController extends EventEmitter { SwapsController: this.swapsController.store, EnsController: this.ensController.store, ApprovalController: this.approvalController, + ///: BEGIN:ONLY_INCLUDE_IN(blockaid) + PPOMController: this.ppomController, + ///: END:ONLY_INCLUDE_IN }; this.store.updateStructure({ @@ -1633,6 +1658,9 @@ export default class MetamaskController extends EventEmitter { this.swapsController.resetState, this.ensController.resetState, this.approvalController.clear.bind(this.approvalController), + ///: BEGIN:ONLY_INCLUDE_IN(blockaid) + this.ppomController.clear.bind(this.ppomController), + ///: END:ONLY_INCLUDE_IN // WE SHOULD ADD TokenListController.resetState here too. But it's not implemented yet. ]; @@ -3910,6 +3938,10 @@ export default class MetamaskController extends EventEmitter { engine.push(createLoggerMiddleware({ origin })); engine.push(this.permissionLogController.createMiddleware()); + ///: BEGIN:ONLY_INCLUDE_IN(blockaid) + engine.push(createPPOMMiddleware(this.ppomController)); + ///: END:ONLY_INCLUDE_IN + engine.push( createRPCMethodTrackingMiddleware({ trackEvent: this.metaMetricsController.trackEvent.bind( diff --git a/builds.yml b/builds.yml index 99311a32d..4ea5e4eb7 100644 --- a/builds.yml +++ b/builds.yml @@ -116,6 +116,7 @@ features: - DISABLE_WEB_SOCKET_ENCRYPTION: false - SKIP_OTP_PAIRING_FLOW: false - WEB_SOCKET_PORT: null + blockaid: ### # Build Type code extensions. Things like different support links, warning pages, banners diff --git a/development/build/static.js b/development/build/static.js index 644105c87..29e6a7ab7 100644 --- a/development/build/static.js +++ b/development/build/static.js @@ -22,19 +22,20 @@ module.exports = function createStaticAssetTasks({ const copyTargetsProds = {}; const copyTargetsDevs = {}; + const buildConfig = loadBuildTypesConfig(); + + const activeFeatures = buildConfig.buildTypes[buildType].features ?? []; + browserPlatforms.forEach((browser) => { const [copyTargetsProd, copyTargetsDev] = getCopyTargets( shouldIncludeLockdown, shouldIncludeSnow, + activeFeatures, ); copyTargetsProds[browser] = copyTargetsProd; copyTargetsDevs[browser] = copyTargetsDev; }); - const buildConfig = loadBuildTypesConfig(); - - const activeFeatures = buildConfig.buildTypes[buildType].features ?? []; - const additionalAssets = activeFeatures.flatMap( (feature) => buildConfig.features[feature].assets?.filter( @@ -108,7 +109,11 @@ module.exports = function createStaticAssetTasks({ } }; -function getCopyTargets(shouldIncludeLockdown, shouldIncludeSnow) { +function getCopyTargets( + shouldIncludeLockdown, + shouldIncludeSnow, + activeFeatures, +) { const allCopyTargets = [ { src: `./app/_locales/`, @@ -198,6 +203,14 @@ function getCopyTargets(shouldIncludeLockdown, shouldIncludeSnow) { }, ]; + if (activeFeatures.includes('blockaid')) { + allCopyTargets.push({ + src: getPathInsideNodeModules('@metamask/ppom-validator', 'dist/'), + pattern: '*.wasm', + dest: '', + }); + } + const languageTags = new Set(); for (const locale of locales) { const { code } = locale; diff --git a/package.json b/package.json index 88754b540..4abcb2bf1 100644 --- a/package.json +++ b/package.json @@ -253,6 +253,7 @@ "@metamask/permission-controller": "^4.0.0", "@metamask/phishing-controller": "^3.0.0", "@metamask/post-message-stream": "^6.0.0", + "@metamask/ppom-validator": "^0.0.1", "@metamask/providers": "^11.1.0", "@metamask/rate-limit-controller": "^3.0.0", "@metamask/rpc-methods": "^1.0.0-prerelease.1", @@ -464,6 +465,7 @@ "eslint-plugin-react": "^7.23.1", "eslint-plugin-react-hooks": "^4.2.0", "eslint-plugin-storybook": "^0.6.12", + "fake-indexeddb": "^4.0.1", "fancy-log": "^1.3.3", "fast-glob": "^3.2.2", "fs-extra": "^8.1.0", diff --git a/yarn.lock b/yarn.lock index 70031d4d3..4db3f92c8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1619,6 +1619,13 @@ __metadata: languageName: node linkType: hard +"@blockaid/ppom-mock@npm:^1.0.0": + version: 1.0.0 + resolution: "@blockaid/ppom-mock@npm:1.0.0" + checksum: 297efc29210aae5fb258bbecefcd742645966041bd9af6f256aa80c671920d5e7d9e669c4d1e34795f8556997663abc42422bfafc511ab8379134ce1c8ac324e + languageName: node + linkType: hard + "@chainsafe/as-sha256@npm:^0.3.1": version: 0.3.1 resolution: "@chainsafe/as-sha256@npm:0.3.1" @@ -4551,6 +4558,18 @@ __metadata: languageName: node linkType: hard +"@metamask/ppom-validator@npm:^0.0.1": + version: 0.0.1 + resolution: "@metamask/ppom-validator@npm:0.0.1" + dependencies: + "@blockaid/ppom-mock": ^1.0.0 + "@metamask/base-controller": ^3.0.0 + "@metamask/controller-utils": ^4.0.0 + await-semaphore: ^0.1.3 + checksum: a94edcd618f670b392a84caa236bbc951a6a99100d8a5fa7bd89b78747c3b06b289738b42aee433659b647441eab0a8741e1951a0e29ef6aa98ffa10a3f33f5b + languageName: node + linkType: hard + "@metamask/preferences-controller@npm:^4.1.0": version: 4.1.0 resolution: "@metamask/preferences-controller@npm:4.1.0" @@ -10703,6 +10722,13 @@ __metadata: languageName: node linkType: hard +"base64-arraybuffer-es6@npm:^0.7.0": + version: 0.7.0 + resolution: "base64-arraybuffer-es6@npm:0.7.0" + checksum: 6d2fd114df49201b476cea5d470504e5d4e8c4cd42544152b312c9bdcb824313086fe83f1ffc34262e9e276b82d46aefc6e63bb85553f016932061137b355cdf + languageName: node + linkType: hard + "base64-arraybuffer@npm:^0.1.5": version: 0.1.5 resolution: "base64-arraybuffer@npm:0.1.5" @@ -14689,10 +14715,12 @@ __metadata: languageName: node linkType: hard -"domexception@npm:^1.0.0": - version: 1.0.0 - resolution: "domexception@npm:1.0.0" - checksum: a580e233689e9dcd5e5322f4b58da618bdbf9c4b96532bd11065903b43e81acbe6ec936ceacc57ce2014b695f778ac6368eb079fe3efb1276073a363d59500a8 +"domexception@npm:^1.0.0, domexception@npm:^1.0.1": + version: 1.0.1 + resolution: "domexception@npm:1.0.1" + dependencies: + webidl-conversions: ^4.0.2 + checksum: f564a9c0915dcb83ceefea49df14aaed106b1468fbe505119e8bcb0b77e242534f3aba861978537c0fc9dc6f35b176d0ffc77b3e342820fb27a8f215e7ae4d52 languageName: node linkType: hard @@ -17083,6 +17111,15 @@ __metadata: languageName: node linkType: hard +"fake-indexeddb@npm:^4.0.1": + version: 4.0.1 + resolution: "fake-indexeddb@npm:4.0.1" + dependencies: + realistic-structured-clone: ^3.0.0 + checksum: dd1c82111e3b97c262a647a29dc012209f8c3bed0fbe7ae9630927772842fe8d3276794ff196d0021a5e60563a25a4323eca622a6a7bc6575b62e074328a0c90 + languageName: node + linkType: hard + "fake-merkle-patricia-tree@npm:^1.0.1": version: 1.0.1 resolution: "fake-merkle-patricia-tree@npm:1.0.1" @@ -23714,7 +23751,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:^4.13.1, lodash@npm:^4.16.4, lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.17.4": +"lodash@npm:^4.13.1, lodash@npm:^4.16.4, lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.17.4, lodash@npm:^4.7.0": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 @@ -24631,6 +24668,7 @@ __metadata: "@metamask/phishing-controller": ^3.0.0 "@metamask/phishing-warning": ^2.1.0 "@metamask/post-message-stream": ^6.0.0 + "@metamask/ppom-validator": ^0.0.1 "@metamask/providers": ^11.1.0 "@metamask/rate-limit-controller": ^3.0.0 "@metamask/rpc-methods": ^1.0.0-prerelease.1 @@ -24769,6 +24807,7 @@ __metadata: ethjs-contract: ^0.2.3 ethjs-query: ^0.3.4 extension-port-stream: ^2.0.0 + fake-indexeddb: ^4.0.1 fancy-log: ^1.3.3 fast-glob: ^3.2.2 fast-json-patch: ^3.1.1 @@ -29794,6 +29833,17 @@ __metadata: languageName: node linkType: hard +"realistic-structured-clone@npm:^3.0.0": + version: 3.0.0 + resolution: "realistic-structured-clone@npm:3.0.0" + dependencies: + domexception: ^1.0.1 + typeson: ^6.1.0 + typeson-registry: ^1.0.0-alpha.20 + checksum: b4521b299c8dc320a5e3ef44678f80a92b0f1837901a5fbd1c7be06808110fb0b591b417114306ec55b44ef47fd17968aacca079afc9665afbe1c528026295ec + languageName: node + linkType: hard + "recast@npm:^0.21.0": version: 0.21.5 resolution: "recast@npm:0.21.5" @@ -33580,6 +33630,15 @@ __metadata: languageName: node linkType: hard +"tr46@npm:^2.1.0": + version: 2.1.0 + resolution: "tr46@npm:2.1.0" + dependencies: + punycode: ^2.1.1 + checksum: ffe6049b9dca3ae329b059aada7f515b0f0064c611b39b51ff6b53897e954650f6f63d9319c6c008d36ead477c7b55e5f64c9dc60588ddc91ff720d64eb710b3 + languageName: node + linkType: hard + "tr46@npm:^3.0.0": version: 3.0.0 resolution: "tr46@npm:3.0.0" @@ -34052,6 +34111,24 @@ __metadata: languageName: node linkType: hard +"typeson-registry@npm:^1.0.0-alpha.20": + version: 1.0.0-alpha.39 + resolution: "typeson-registry@npm:1.0.0-alpha.39" + dependencies: + base64-arraybuffer-es6: ^0.7.0 + typeson: ^6.0.0 + whatwg-url: ^8.4.0 + checksum: c6b629697acf4652aecfff7be760356d764600afc9beca253278bbfc44fae0fe635b7619201b83e497cdc30645cbce7614d12a04b5726d9b8b505f73e6a3fc2a + languageName: node + linkType: hard + +"typeson@npm:^6.0.0, typeson@npm:^6.1.0": + version: 6.1.0 + resolution: "typeson@npm:6.1.0" + checksum: 00a77b03ac8f704acb103307bad9295fe47d6b304c386297f078ec3be63875c0b81e022a4815edb9dc2c7da0a72a431345411d35c755a8510af4a420e9e46cdc + languageName: node + linkType: hard + "uglify-js@npm:^3.1.4": version: 3.17.0 resolution: "uglify-js@npm:3.17.0" @@ -35404,6 +35481,13 @@ __metadata: languageName: node linkType: hard +"webidl-conversions@npm:^6.1.0": + version: 6.1.0 + resolution: "webidl-conversions@npm:6.1.0" + checksum: 1f526507aa491f972a0c1409d07f8444e1d28778dfa269a9971f2e157182f3d496dc33296e4ed45b157fdb3bf535bb90c90bf10c50dcf1dd6caacb2a34cc84fb + languageName: node + linkType: hard + "webidl-conversions@npm:^7.0.0": version: 7.0.0 resolution: "webidl-conversions@npm:7.0.0" @@ -35578,6 +35662,17 @@ __metadata: languageName: node linkType: hard +"whatwg-url@npm:^8.4.0": + version: 8.7.0 + resolution: "whatwg-url@npm:8.7.0" + dependencies: + lodash: ^4.7.0 + tr46: ^2.1.0 + webidl-conversions: ^6.1.0 + checksum: a87abcc6cefcece5311eb642858c8fdb234e51ec74196bfacf8def2edae1bfbffdf6acb251646ed6301f8cee44262642d8769c707256125a91387e33f405dd1e + languageName: node + linkType: hard + "which-boxed-primitive@npm:^1.0.2": version: 1.0.2 resolution: "which-boxed-primitive@npm:1.0.2" From c2062009188246a593d7e5b1d72e2fb1dff7d870 Mon Sep 17 00:00:00 2001 From: Garrett Bear Date: Wed, 12 Jul 2023 07:37:33 -0700 Subject: [PATCH 012/172] Update ButtonBase text variant and fix font smoothing (#19883) * Update ButtonBase text variant --------- Co-authored-by: Nidhi Kumari --- .../__snapshots__/custom-spending-cap.test.js.snap | 4 ++-- .../__snapshots__/ledger-instruction-field.test.js.snap | 2 +- .../__snapshots__/eth-sign-modal.test.js.snap | 6 +++--- .../__snapshots__/export-private-key-modal.test.js.snap | 4 ++-- .../button-base/__snapshots__/button-base.test.js.snap | 4 ++-- .../component-library/button-base/button-base.js | 1 + .../button-link/__snapshots__/button-link.test.js.snap | 2 +- .../__snapshots__/button-primary.test.js.snap | 2 +- .../__snapshots__/button-secondary.test.js.snap | 2 +- .../button/__snapshots__/button.test.js.snap | 8 ++++---- .../__snapshots__/compliance-settings.test.js.snap | 6 +++--- .../__snapshots__/confirm-remove-jwt-modal.test.js.snap | 2 +- .../__snapshots__/custody-confirm-link-modal.test.js.snap | 2 +- .../__snapshots__/account-list-item.test.js.snap | 2 +- .../__snapshots__/account-picker.test.js.snap | 2 +- .../app-header/__snapshots__/app-header.test.js.snap | 2 +- .../__snapshots__/detected-token-banner.test.js.snap | 2 +- .../import-account/__snapshots__/json.test.tsx.snap | 6 +++--- .../__snapshots__/import-token-link.test.js.snap | 8 ++++---- .../__snapshots__/network-list-item.test.js.snap | 2 +- .../__snapshots__/desktop-pairing.test.js.snap | 2 +- .../__snapshots__/account-list.test.js.snap | 4 ++-- .../custody/__snapshots__/custody.test.js.snap | 2 +- ui/pages/keychains/__snapshots__/reveal-seed.test.js.snap | 8 ++++---- .../__snapshots__/snap-account-detail-page.test.tsx.snap | 8 ++++---- .../snap-card/__snapshots__/snap-card.test.tsx.snap | 2 +- .../security-tab/__snapshots__/security-tab.test.js.snap | 4 ++-- .../__snapshots__/token-allowance.test.js.snap | 4 ++-- 28 files changed, 52 insertions(+), 51 deletions(-) diff --git a/ui/components/app/custom-spending-cap/__snapshots__/custom-spending-cap.test.js.snap b/ui/components/app/custom-spending-cap/__snapshots__/custom-spending-cap.test.js.snap index 2b2dff9b4..94518221a 100644 --- a/ui/components/app/custom-spending-cap/__snapshots__/custom-spending-cap.test.js.snap +++ b/ui/components/app/custom-spending-cap/__snapshots__/custom-spending-cap.test.js.snap @@ -67,7 +67,7 @@ exports[`CustomSpendingCap should match snapshot 1`] = ` class="box custom-spending-cap__max box--margin-left-auto box--padding-right-4 box--padding-bottom-2 box--flex-direction-row box--text-align-end box--width-max" > @@ -93,7 +93,7 @@ exports[`CustomSpendingCap should match snapshot 1`] = ` diff --git a/ui/components/app/ledger-instruction-field/__snapshots__/ledger-instruction-field.test.js.snap b/ui/components/app/ledger-instruction-field/__snapshots__/ledger-instruction-field.test.js.snap index 4dc118b20..1d259f4b9 100644 --- a/ui/components/app/ledger-instruction-field/__snapshots__/ledger-instruction-field.test.js.snap +++ b/ui/components/app/ledger-instruction-field/__snapshots__/ledger-instruction-field.test.js.snap @@ -37,7 +37,7 @@ exports[`LedgerInstructionField Component rendering should render properly with > diff --git a/ui/components/app/modals/eth-sign-modal/__snapshots__/eth-sign-modal.test.js.snap b/ui/components/app/modals/eth-sign-modal/__snapshots__/eth-sign-modal.test.js.snap index d0c0d7d53..6cf56f801 100644 --- a/ui/components/app/modals/eth-sign-modal/__snapshots__/eth-sign-modal.test.js.snap +++ b/ui/components/app/modals/eth-sign-modal/__snapshots__/eth-sign-modal.test.js.snap @@ -32,7 +32,7 @@ exports[`Eth Sign Modal should match snapshot 1`] = ` > Allowing eth_sign requests can make you vulnerable to phishing attacks. Always review the URL and be careful when signing messages that contain code. diff --git a/ui/components/multichain/account-list-item/__snapshots__/account-list-item.test.js.snap b/ui/components/multichain/account-list-item/__snapshots__/account-list-item.test.js.snap index 2afc7f4ed..13fb9415e 100644 --- a/ui/components/multichain/account-list-item/__snapshots__/account-list-item.test.js.snap +++ b/ui/components/multichain/account-list-item/__snapshots__/account-list-item.test.js.snap @@ -61,7 +61,7 @@ exports[`AccountListItem renders AccountListItem component and shows account nam class="box mm-text multichain-account-list-item__account-name mm-text--body-md mm-text--ellipsis box--margin-inline-end-2 box--flex-direction-row box--color-text-default" > diff --git a/ui/components/multichain/import-account/__snapshots__/json.test.tsx.snap b/ui/components/multichain/import-account/__snapshots__/json.test.tsx.snap index 295c50e24..763497971 100644 --- a/ui/components/multichain/import-account/__snapshots__/json.test.tsx.snap +++ b/ui/components/multichain/import-account/__snapshots__/json.test.tsx.snap @@ -7,7 +7,7 @@ exports[`Json should match snapshot 1`] = ` > Used by a variety of different clients diff --git a/ui/pages/institutional/connect-custody/__snapshots__/account-list.test.js.snap b/ui/pages/institutional/connect-custody/__snapshots__/account-list.test.js.snap index 28ada1a91..ef1ca080f 100644 --- a/ui/pages/institutional/connect-custody/__snapshots__/account-list.test.js.snap +++ b/ui/pages/institutional/connect-custody/__snapshots__/account-list.test.js.snap @@ -44,7 +44,7 @@ exports[`CustodyAccountList renders accounts 1`] = ` class="box mm-text custody-account-list__item mm-text--body-md box--display-flex box--flex-direction-row box--color-text-default" > @@ -42,7 +42,7 @@ exports[`SnapAccountDetails should take a snapshot 1`] = ` class="mm-box" > @@ -180,7 +180,7 @@ exports[`SnapAccountDetails should take a snapshot 1`] = ` class="box mm-text mm-text--body-md box--flex-direction-row box--color-text-default" > auditUrl1 @@ -190,7 +190,7 @@ exports[`SnapAccountDetails should take a snapshot 1`] = ` class="box mm-text mm-text--body-md box--flex-direction-row box--color-text-default" > auditUrl2 diff --git a/ui/pages/keyring-snaps/snap-card/__snapshots__/snap-card.test.tsx.snap b/ui/pages/keyring-snaps/snap-card/__snapshots__/snap-card.test.tsx.snap index 01cf8ff49..4a9664988 100644 --- a/ui/pages/keyring-snaps/snap-card/__snapshots__/snap-card.test.tsx.snap +++ b/ui/pages/keyring-snaps/snap-card/__snapshots__/snap-card.test.tsx.snap @@ -24,7 +24,7 @@ exports[`SnapCard should render 1`] = ` @@ -433,7 +433,7 @@ exports[`TokenAllowancePage should match snapshot 1`] = ` From e329818dab55b07e2c9fa525e82edb4ddec0f901 Mon Sep 17 00:00:00 2001 From: David Walsh Date: Wed, 12 Jul 2023 11:05:41 -0500 Subject: [PATCH 013/172] Fix #19548 - Increase address copy to clipboard time (#19948) --- .../multichain/address-copy-button/address-copy-button.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/components/multichain/address-copy-button/address-copy-button.js b/ui/components/multichain/address-copy-button/address-copy-button.js index 953bff31a..a46affac0 100644 --- a/ui/components/multichain/address-copy-button/address-copy-button.js +++ b/ui/components/multichain/address-copy-button/address-copy-button.js @@ -14,6 +14,7 @@ import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard'; import { shortenAddress } from '../../../helpers/utils/util'; import Tooltip from '../../ui/tooltip/tooltip'; import { useI18nContext } from '../../../hooks/useI18nContext'; +import { MINUTE } from '../../../../shared/constants/time'; export const AddressCopyButton = ({ address, @@ -22,7 +23,7 @@ export const AddressCopyButton = ({ onClick, }) => { const displayAddress = shorten ? shortenAddress(address) : address; - const [copied, handleCopy] = useCopyToClipboard(); + const [copied, handleCopy] = useCopyToClipboard(MINUTE); const t = useI18nContext(); return ( From 23c3e8f32df832e8e2d38e9d45f10d2f90fdf3d6 Mon Sep 17 00:00:00 2001 From: jainex Date: Wed, 12 Jul 2023 22:10:12 +0530 Subject: [PATCH 014/172] Replacing deprecated constants with enums (#19860) --- .../confirmation-network-switch.js | 30 +++++++++---------- .../templates/add-ethereum-chain.js | 30 +++++++++---------- .../list-with-search/list-with-search.js | 14 ++++----- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/ui/pages/confirmation/components/confirmation-network-switch/confirmation-network-switch.js b/ui/pages/confirmation/components/confirmation-network-switch/confirmation-network-switch.js index 7f0775e38..4af4e9e1c 100644 --- a/ui/pages/confirmation/components/confirmation-network-switch/confirmation-network-switch.js +++ b/ui/pages/confirmation/components/confirmation-network-switch/confirmation-network-switch.js @@ -6,12 +6,12 @@ import SiteIcon from '../../../../components/ui/site-icon'; import Typography from '../../../../components/ui/typography/typography'; import { TypographyVariant, - FONT_WEIGHT, - DISPLAY, + FontWeight, + Display, JustifyContent, - BLOCK_SIZES, + BlockSize, AlignItems, - TEXT_ALIGN, + TextAlign, TextColor, } from '../../../../helpers/constants/design-system'; import { @@ -26,14 +26,14 @@ export default function ConfirmationNetworkSwitch({ newNetwork }) { return ( {chainId in CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP ? ( @@ -61,7 +61,7 @@ export default function ConfirmationNetworkSwitch({ newNetwork }) { @@ -70,7 +70,7 @@ export default function ConfirmationNetworkSwitch({ newNetwork }) { {newNetwork.chainId in CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP ? ( diff --git a/ui/pages/confirmation/templates/add-ethereum-chain.js b/ui/pages/confirmation/templates/add-ethereum-chain.js index 362a8d797..6bf2d3cd9 100644 --- a/ui/pages/confirmation/templates/add-ethereum-chain.js +++ b/ui/pages/confirmation/templates/add-ethereum-chain.js @@ -2,11 +2,11 @@ import { ethErrors } from 'eth-rpc-errors'; import React from 'react'; import { infuraProjectId } from '../../../../shared/constants/network'; import { - SEVERITIES, + Severity, TypographyVariant, - TEXT_ALIGN, - DISPLAY, - FLEX_DIRECTION, + TextAlign, + Display, + FlexDirection, AlignItems, JustifyContent, BackgroundColor, @@ -18,7 +18,7 @@ import { jsonRpcRequest } from '../../../../shared/modules/rpc.utils'; const UNRECOGNIZED_CHAIN = { id: 'UNRECOGNIZED_CHAIN', - severity: SEVERITIES.WARNING, + severity: Severity.Warning, content: { element: 'span', children: { @@ -32,7 +32,7 @@ const UNRECOGNIZED_CHAIN = { const MISMATCHED_CHAIN_RECOMMENDATION = { id: 'MISMATCHED_CHAIN_RECOMMENDATION', - severity: SEVERITIES.WARNING, + severity: Severity.Warning, content: { element: 'span', children: { @@ -63,7 +63,7 @@ const MISMATCHED_CHAIN_RECOMMENDATION = { const MISMATCHED_NETWORK_NAME = { id: 'MISMATCHED_NETWORK_NAME', - severity: SEVERITIES.WARNING, + severity: Severity.Warning, content: { element: 'span', children: { @@ -77,7 +77,7 @@ const MISMATCHED_NETWORK_NAME = { const MISMATCHED_NETWORK_SYMBOL = { id: 'MISMATCHED_NETWORK_SYMBOL', - severity: SEVERITIES.DANGER, + severity: Severity.Danger, content: { element: 'span', children: { @@ -91,7 +91,7 @@ const MISMATCHED_NETWORK_SYMBOL = { const MISMATCHED_NETWORK_RPC = { id: 'MISMATCHED_NETWORK_RPC', - severity: SEVERITIES.DANGER, + severity: Severity.Danger, content: { element: 'span', children: { @@ -105,7 +105,7 @@ const MISMATCHED_NETWORK_RPC = { const MISMATCHED_NETWORK_RPC_CHAIN_ID = { id: 'MISMATCHED_NETWORK_RPC_CHAIN_ID', - severity: SEVERITIES.DANGER, + severity: Severity.Danger, content: { element: 'span', children: { @@ -119,7 +119,7 @@ const MISMATCHED_NETWORK_RPC_CHAIN_ID = { const ERROR_CONNECTING_TO_RPC = { id: 'ERROR_CONNECTING_TO_RPC', - severity: SEVERITIES.DANGER, + severity: Severity.Danger, content: { element: 'span', children: { @@ -192,8 +192,8 @@ function getValues(pendingApproval, t, actions, history) { element: 'Box', key: 'network-box', props: { - textAlign: TEXT_ALIGN.CENTER, - display: DISPLAY.FLEX, + textAlign: TextAlign.Center, + display: Display.Flex, justifyContent: JustifyContent.center, marginTop: 4, marginBottom: 2, @@ -318,8 +318,8 @@ function getValues(pendingApproval, t, actions, history) { variant: TypographyVariant.H7, boxProps: { margin: originIsMetaMask ? [0, 8] : 0, - display: DISPLAY.FLEX, - flexDirection: FLEX_DIRECTION.COLUMN, + display: Display.Flex, + flexDirection: FlexDirection.Column, alignItems: AlignItems.center, }, }, diff --git a/ui/pages/swaps/list-with-search/list-with-search.js b/ui/pages/swaps/list-with-search/list-with-search.js index 64223da18..aeddbacb1 100644 --- a/ui/pages/swaps/list-with-search/list-with-search.js +++ b/ui/pages/swaps/list-with-search/list-with-search.js @@ -6,12 +6,12 @@ import log from 'loglevel'; import Box from '../../../components/ui/box'; import { - DISPLAY, - FLEX_DIRECTION, + Display, + FlexDirection, JustifyContent, AlignItems, TextVariant, - BLOCK_SIZES, + BlockSize, } from '../../../helpers/constants/design-system'; import { TextFieldSearch, Text } from '../../../components/component-library'; import ItemList from '../searchable-item-list/item-list'; @@ -112,11 +112,11 @@ export default function ListWithSearch({ }; return ( - + From c86cbf5df2d8d3eb4cd9f5cd8f82fb45d2b8930c Mon Sep 17 00:00:00 2001 From: Dhruv <79097544+dhruvv173@users.noreply.github.com> Date: Wed, 12 Jul 2023 22:12:24 +0530 Subject: [PATCH 015/172] Replacing deprecated constants (#19858) --- .../detected-token-aggregators.js | 13 +++++-------- .../detected-token-aggregators.stories.js | 6 +++--- .../detected-token-details.js | 8 ++++---- .../detected-token-details.stories.js | 2 +- .../detected-token-values/detected-token-values.js | 7 +++---- 5 files changed, 16 insertions(+), 20 deletions(-) diff --git a/ui/components/app/detected-token/detected-token-aggregators/detected-token-aggregators.js b/ui/components/app/detected-token/detected-token-aggregators/detected-token-aggregators.js index 7052eabbc..ac3af6bff 100644 --- a/ui/components/app/detected-token/detected-token-aggregators/detected-token-aggregators.js +++ b/ui/components/app/detected-token/detected-token-aggregators/detected-token-aggregators.js @@ -3,14 +3,12 @@ import PropTypes from 'prop-types'; import { useI18nContext } from '../../../../hooks/useI18nContext'; -import Box from '../../../ui/box'; -import Button from '../../../ui/button'; import { - DISPLAY, + Display, FontWeight, TextVariant, } from '../../../../helpers/constants/design-system'; -import { Text } from '../../../component-library'; +import { Text, Box, ButtonLink } from '../../../component-library'; const NUMBER_OF_AGGREGATORS_TO_DISPLAY = 2; @@ -21,7 +19,7 @@ const DetectedTokenAggregators = ({ aggregators }) => { const [displayMore, setDisplayMore] = useState(false); return ( - + {t('fromTokenLists', [ numOfHiddenAggregators > 0 && !displayMore ? ( @@ -34,14 +32,13 @@ const DetectedTokenAggregators = ({ aggregators }) => { {`${aggregators .slice(0, NUMBER_OF_AGGREGATORS_TO_DISPLAY) .join(', ')}`} - + ) : ( { return ( - + diff --git a/ui/components/app/detected-token/detected-token-details/detected-token-details.js b/ui/components/app/detected-token/detected-token-details/detected-token-details.js index 7bd87f5b4..3fb321963 100644 --- a/ui/components/app/detected-token/detected-token-details/detected-token-details.js +++ b/ui/components/app/detected-token/detected-token-details/detected-token-details.js @@ -2,12 +2,12 @@ import React from 'react'; import PropTypes from 'prop-types'; import { useSelector } from 'react-redux'; -import Box from '../../../ui/box'; +import { Box } from '../../../component-library'; import Identicon from '../../../ui/identicon'; import DetectedTokenValues from '../detected-token-values/detected-token-values'; import DetectedTokenAddress from '../detected-token-address/detected-token-address'; import DetectedTokenAggregators from '../detected-token-aggregators/detected-token-aggregators'; -import { DISPLAY } from '../../../../helpers/constants/design-system'; +import { Display } from '../../../../helpers/constants/design-system'; import { getTokenList } from '../../../../selectors'; const DetectedTokenDetails = ({ @@ -20,7 +20,7 @@ const DetectedTokenDetails = ({ return ( @@ -30,7 +30,7 @@ const DetectedTokenDetails = ({ diameter={40} /> diff --git a/ui/components/app/detected-token/detected-token-details/detected-token-details.stories.js b/ui/components/app/detected-token/detected-token-details/detected-token-details.stories.js index 360f20e93..68dcdc8a2 100644 --- a/ui/components/app/detected-token/detected-token-details/detected-token-details.stories.js +++ b/ui/components/app/detected-token/detected-token-details/detected-token-details.stories.js @@ -7,7 +7,7 @@ export default { argTypes: { token: { control: 'object' }, - handleTokenSelection: { control: 'func' }, + handleTokenSelection: { action: 'handleTokenSelection' }, tokensListDetected: { control: 'array' }, }, args: { diff --git a/ui/components/app/detected-token/detected-token-values/detected-token-values.js b/ui/components/app/detected-token/detected-token-values/detected-token-values.js index 67d16c946..6d1a95470 100644 --- a/ui/components/app/detected-token/detected-token-values/detected-token-values.js +++ b/ui/components/app/detected-token/detected-token-values/detected-token-values.js @@ -2,18 +2,17 @@ import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { useSelector } from 'react-redux'; -import Box from '../../../ui/box'; import CheckBox from '../../../ui/check-box'; import { - DISPLAY, + Display, TextColor, TextVariant, } from '../../../../helpers/constants/design-system'; import { useTokenTracker } from '../../../../hooks/useTokenTracker'; import { useTokenFiatAmount } from '../../../../hooks/useTokenFiatAmount'; import { getUseCurrencyRateCheck } from '../../../../selectors'; -import { Text } from '../../../component-library'; +import { Text, Box } from '../../../component-library'; const DetectedTokenValues = ({ token, @@ -44,7 +43,7 @@ const DetectedTokenValues = ({ }; return ( - + {`${balanceString || '0'} ${token.symbol}`} From beffc0611fb68d3176f6b3b5b77ac4bdea2269be Mon Sep 17 00:00:00 2001 From: Nidhi Kumari Date: Wed, 12 Jul 2023 22:57:39 +0530 Subject: [PATCH 016/172] UX Multichain: Replace badge icon with current network image (#19964) * updated network with current network * Update snapshot * fixed stories --------- Co-authored-by: David Walsh --- .../__snapshots__/token-cell.test.js.snap | 2 +- .../token-list-item.test.js.snap | 2 +- .../token-list-item/token-list-item.js | 25 ++++++++-------- .../token-list-item.stories.js | 30 ++++++++++++------- 4 files changed, 34 insertions(+), 25 deletions(-) diff --git a/ui/components/app/token-cell/__snapshots__/token-cell.test.js.snap b/ui/components/app/token-cell/__snapshots__/token-cell.test.js.snap index 7c0f9962a..4c3313957 100644 --- a/ui/components/app/token-cell/__snapshots__/token-cell.test.js.snap +++ b/ui/components/app/token-cell/__snapshots__/token-cell.test.js.snap @@ -26,7 +26,7 @@ exports[`Token Cell should match snapshot 1`] = ` class="box mm-text mm-avatar-base mm-avatar-base--size-xs mm-avatar-network mm-text--body-xs mm-text--text-transform-uppercase box--display-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-text-default box--background-color-background-alternative box--rounded-full box--border-color-border-muted box--border-style-solid box--border-width-1" > TEST logo diff --git a/ui/components/multichain/token-list-item/__snapshots__/token-list-item.test.js.snap b/ui/components/multichain/token-list-item/__snapshots__/token-list-item.test.js.snap index cb0c57a11..11642e4db 100644 --- a/ui/components/multichain/token-list-item/__snapshots__/token-list-item.test.js.snap +++ b/ui/components/multichain/token-list-item/__snapshots__/token-list-item.test.js.snap @@ -26,7 +26,7 @@ exports[`TokenListItem should render correctly 1`] = ` class="box mm-text mm-avatar-base mm-avatar-base--size-xs mm-avatar-network mm-text--body-xs mm-text--text-transform-uppercase box--display-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-text-default box--background-color-background-alternative box--rounded-full box--border-color-border-muted box--border-style-solid box--border-width-1" > undefined logo diff --git a/ui/components/multichain/token-list-item/token-list-item.js b/ui/components/multichain/token-list-item/token-list-item.js index 6a517411f..d305660c9 100644 --- a/ui/components/multichain/token-list-item/token-list-item.js +++ b/ui/components/multichain/token-list-item/token-list-item.js @@ -21,7 +21,11 @@ import { Text, Box, } from '../../component-library'; -import { getCurrentChainId, getNativeCurrencyImage } from '../../../selectors'; +import { + getCurrentChainId, + getCurrentNetwork, + getNativeCurrencyImage, +} from '../../../selectors'; import Tooltip from '../../ui/tooltip'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { MetaMetricsContext } from '../../../contexts/metametrics'; @@ -29,7 +33,6 @@ import { MetaMetricsEventCategory, MetaMetricsEventName, } from '../../../../shared/constants/metametrics'; -import { LINEA_GOERLI_TOKEN_IMAGE_URL } from '../../../../shared/constants/network'; export const TokenListItem = ({ className, @@ -44,11 +47,9 @@ export const TokenListItem = ({ const primaryTokenImage = useSelector(getNativeCurrencyImage); const trackEvent = useContext(MetaMetricsContext); const chainId = useSelector(getCurrentChainId); - const badgeWrapperImage = - title === 'LineaETH' ? LINEA_GOERLI_TOKEN_IMAGE_URL : primaryTokenImage; - const badgeTokenImage = - title === 'LineaETH' ? LINEA_GOERLI_TOKEN_IMAGE_URL : tokenImage; + // Used for badge icon + const currentNetwork = useSelector(getCurrentNetwork); return ( diff --git a/ui/components/multichain/token-list-item/token-list-item.stories.js b/ui/components/multichain/token-list-item/token-list-item.stories.js index 73af87ec8..51cbbfb5e 100644 --- a/ui/components/multichain/token-list-item/token-list-item.stories.js +++ b/ui/components/multichain/token-list-item/token-list-item.stories.js @@ -38,7 +38,12 @@ export default { const customNetworkData = { ...testData, - metamask: { ...testData.metamask, nativeCurrency: '' }, + metamask: { + ...testData.metamask, + providerConfig: { + chainId: '0x1', + }, + }, }; const customNetworkStore = configureStore(customNetworkData); @@ -47,6 +52,13 @@ const Template = (args) => { }; export const DefaultStory = Template.bind({}); +DefaultStory.decorators = [ + (Story) => ( + + + + ), +]; export const ChaosStory = (args) => (
(
); -ChaosStory.storyName = 'ChaosStory'; +ChaosStory.decorators = [ + (Story) => ( + + + + ), +]; ChaosStory.args = { title: 'Really long, long name', @@ -65,14 +83,6 @@ ChaosStory.args = { export const NoImagesStory = Template.bind({}); -NoImagesStory.decorators = [ - (Story) => ( - - - - ), -]; - NoImagesStory.args = { tokenImage: '', }; From c7782563c8de5ee83cf2f6a620004e5c8b536c73 Mon Sep 17 00:00:00 2001 From: Jase Balderrama <4392888+jase-b@users.noreply.github.com> Date: Wed, 12 Jul 2023 10:47:15 -0700 Subject: [PATCH 017/172] Fix misaligned icons in 'Connected sites' modal (#19944) * Replace w/ * Use constant values for borderColor & size Co-authored-by: Nidhi Kumari --------- Co-authored-by: Nidhi Kumari --- .../connected-sites-list.component.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ui/components/app/connected-sites-list/connected-sites-list.component.js b/ui/components/app/connected-sites-list/connected-sites-list.component.js index 00372f64e..72b4cacfe 100644 --- a/ui/components/app/connected-sites-list/connected-sites-list.component.js +++ b/ui/components/app/connected-sites-list/connected-sites-list.component.js @@ -1,9 +1,10 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import Button from '../../ui/button'; -import SiteIcon from '../../ui/site-icon'; +import { AvatarFavicon } from '../../component-library'; import { stripHttpsSchemeWithoutPort } from '../../../helpers/utils/util'; import SiteOrigin from '../../ui/site-origin'; +import { BorderColor, Size } from '../../../helpers/constants/design-system'; export default class ConnectedSitesList extends Component { static contextTypes = { @@ -33,11 +34,12 @@ export default class ConnectedSitesList extends Component { className="connected-sites-list__content-row" >
- Date: Wed, 12 Jul 2023 19:27:44 +0100 Subject: [PATCH 018/172] fix flakiness in mv3 multiple restart test (#19708) * fix flakiness in mv3 multiple restart test * tweak msgs * refactor * refactor * remove unused function --- test/e2e/helpers.js | 13 ++--- test/e2e/mv3/multiple-restarts.spec.js | 72 +++++++++++++------------- test/e2e/webdriver/driver.js | 6 ++- 3 files changed, 44 insertions(+), 47 deletions(-) diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index 8c0ffb76a..2e7b224e9 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -692,12 +692,6 @@ function generateRandNumBetween(x, y) { return randomNumber; } -async function switchToWindow(driver, windowTitle) { - const windowHandles = await driver.getAllWindowHandles(); - - return await driver.switchToWindowWithTitle(windowTitle, windowHandles); -} - async function sleepSeconds(sec) { return new Promise((resolve) => setTimeout(resolve, sec * 1000)); } @@ -714,7 +708,8 @@ async function terminateServiceWorker(driver) { tag: 'button', }); - const serviceWorkerElements = await driver.findElements({ + await driver.delay(tinyDelayMs); + const serviceWorkerElements = await driver.findClickableElements({ text: 'terminate', tag: 'span', }); @@ -722,8 +717,7 @@ async function terminateServiceWorker(driver) { // 1st one is app-init.js; while 2nd one is service-worker.js await serviceWorkerElements[serviceWorkerElements.length - 1].click(); - const serviceWorkerTab = await switchToWindow( - driver, + const serviceWorkerTab = await driver.switchToWindowWithTitle( WINDOW_TITLES.ServiceWorkerSettings, ); @@ -810,7 +804,6 @@ module.exports = { generateETHBalance, roundToXDecimalPlaces, generateRandNumBetween, - switchToWindow, sleepSeconds, terminateServiceWorker, switchToNotificationWindow, diff --git a/test/e2e/mv3/multiple-restarts.spec.js b/test/e2e/mv3/multiple-restarts.spec.js index 91f34896d..c2b636c01 100644 --- a/test/e2e/mv3/multiple-restarts.spec.js +++ b/test/e2e/mv3/multiple-restarts.spec.js @@ -9,10 +9,10 @@ const { generateETHBalance, roundToXDecimalPlaces, generateRandNumBetween, - switchToWindow, sleepSeconds, terminateServiceWorker, unlockWallet, + largeDelayMs, } = require('../helpers'); const FixtureBuilder = require('../fixture-builder'); @@ -114,7 +114,9 @@ describe('MV3 - Restart service worker multiple times', function () { ); async function simpleSendETH(driver, value, recipient) { - await switchToWindow(driver, WINDOW_TITLES.ExtensionInFullScreenView); + await driver.switchToWindowWithTitle( + WINDOW_TITLES.ExtensionInFullScreenView, + ); await driver.clickElement('[data-testid="eth-overview-send"]'); await driver.fill('[data-testid="ens-input"]', recipient); @@ -138,7 +140,9 @@ describe('MV3 - Restart service worker multiple times', function () { } async function assertETHBalance(driver, expectedBalance) { - await switchToWindow(driver, WINDOW_TITLES.ExtensionInFullScreenView); + await driver.switchToWindowWithTitle( + WINDOW_TITLES.ExtensionInFullScreenView, + ); const isETHBalanceOverviewPresentAndVisible = await driver.isElementPresentAndVisible({ @@ -175,12 +179,11 @@ describe('MV3 - Restart service worker multiple times', function () { await openDapp(driver); // Click add Ethereum chain - await switchToWindow(driver, WINDOW_TITLES.TestDApp); + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp); await driver.clickElement('#addEthereumChain'); - await driver.waitUntilXWindowHandles(2); // Notification pop up opens - await switchToWindow(driver, WINDOW_TITLES.Notification); + await driver.switchToWindowWithTitle(WINDOW_TITLES.Notification); let notification = await driver.isElementPresent({ text: 'Allow this site to add a network?', tag: 'h3', @@ -189,19 +192,18 @@ describe('MV3 - Restart service worker multiple times', function () { // Cancel Notification await driver.clickElement({ text: 'Cancel', tag: 'button' }); - await driver.waitUntilXWindowHandles(2); // Terminate Service Worker - await switchToWindow(driver, WINDOW_TITLES.TestDApp); + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp); + await terminateServiceWorker(driver); // Click add Ethereum chain #2 - await switchToWindow(driver, WINDOW_TITLES.TestDApp); + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp); await driver.clickElement('#addEthereumChain'); - await driver.waitUntilXWindowHandles(2); // Notification pop up opens - await switchToWindow(driver, WINDOW_TITLES.Notification); + await driver.switchToWindowWithTitle(WINDOW_TITLES.Notification); notification = await driver.isElementPresent({ text: 'Allow this site to add a network?', tag: 'h3', @@ -210,19 +212,17 @@ describe('MV3 - Restart service worker multiple times', function () { // Cancel Notification await driver.clickElement({ text: 'Cancel', tag: 'button' }); - await driver.waitUntilXWindowHandles(2); // Terminate Service Worker - await switchToWindow(driver, WINDOW_TITLES.TestDApp); + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp); await terminateServiceWorker(driver); // Click add Ethereum chain #3 - await switchToWindow(driver, WINDOW_TITLES.TestDApp); + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp); await driver.clickElement('#addEthereumChain'); - await driver.waitUntilXWindowHandles(2); // Notification pop up opens - await switchToWindow(driver, WINDOW_TITLES.Notification); + await driver.switchToWindowWithTitle(WINDOW_TITLES.Notification); notification = await driver.isElementPresent({ text: 'Allow this site to add a network?', tag: 'h3', @@ -232,7 +232,6 @@ describe('MV3 - Restart service worker multiple times', function () { // Accept Notification await driver.clickElement({ text: 'Approve', tag: 'button' }); await driver.clickElement({ text: 'Switch network', tag: 'button' }); - await driver.waitUntilXWindowHandles(2); }, ); }); @@ -257,21 +256,20 @@ describe('MV3 - Restart service worker multiple times', function () { await openDapp(driver); - await clickSendButton(driver); - await driver.waitUntilXWindowHandles(2); - - await switchToWindow(driver, WINDOW_TITLES.TestDApp); - await terminateServiceWorker(driver); - await driver.waitUntilXWindowHandles(2); + await driver.delay(largeDelayMs); await clickSendButton(driver); - await driver.waitUntilXWindowHandles(2); - await switchToWindow(driver, WINDOW_TITLES.TestDApp); + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp); + + await terminateServiceWorker(driver); + + await clickSendButton(driver); + + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp); await terminateServiceWorker(driver); await clickSendButton(driver); - await driver.waitUntilXWindowHandles(2); await assertNumberOfTransactionsInPopUp(driver, 3); @@ -287,7 +285,7 @@ describe('MV3 - Restart service worker multiple times', function () { async function clickSendButton(driver) { // Click send button - await switchToWindow(driver, WINDOW_TITLES.TestDApp); + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp); await driver.waitForSelector({ css: '#sendButton', @@ -297,7 +295,7 @@ describe('MV3 - Restart service worker multiple times', function () { } async function confirmETHSendNotification(driver, amount) { - await switchToWindow(driver, WINDOW_TITLES.Notification); + await driver.switchToWindowWithTitle(WINDOW_TITLES.Notification); await driver.clickElement({ text: 'Edit', @@ -318,14 +316,16 @@ describe('MV3 - Restart service worker multiple times', function () { } async function assertNumberOfTransactionsInPopUp(driver, number) { - await switchToWindow(driver, WINDOW_TITLES.Notification); - const navEl = await driver.findElement( - '.confirm-page-container-navigation__navtext', - ); + await driver.delay(largeDelayMs); - const notificationProgress = await navEl.getText(); + await driver.switchToWindowWithTitle(WINDOW_TITLES.Notification); - assert.ok(notificationProgress, `1 of ${number}`); + const foundElement = await driver.findElements({ + css: '.confirm-page-container-navigation__navtext', + text: `1 of ${number}`, + }); + + assert.ok(foundElement, true); } }); @@ -365,7 +365,9 @@ describe('MV3 - Restart service worker multiple times', function () { ); async function reloadExtension(driver, extensionId) { - await switchToWindow(driver, WINDOW_TITLES.ExtensionInFullScreenView); + await driver.switchToWindowWithTitle( + WINDOW_TITLES.ExtensionInFullScreenView, + ); await driver.openNewPage('chrome://extensions/'); diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index c1284f70c..f3e4ccb1f 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -58,7 +58,7 @@ class Driver { * @param extensionUrl * @param {number} timeout */ - constructor(driver, browser, extensionUrl, timeout = 10000) { + constructor(driver, browser, extensionUrl, timeout = 10 * 1000) { this.driver = driver; this.browser = browser; this.extensionUrl = extensionUrl; @@ -376,6 +376,7 @@ class Driver { let windowHandles = []; while (timeElapsed <= timeout) { windowHandles = await this.driver.getAllWindowHandles(); + if (windowHandles.length === x) { return windowHandles; } @@ -389,7 +390,7 @@ class Driver { title, initialWindowHandles, delayStep = 1000, - timeout = 5000, + timeout = this.timeout, ) { let windowHandles = initialWindowHandles || (await this.driver.getAllWindowHandles()); @@ -397,6 +398,7 @@ class Driver { while (timeElapsed <= timeout) { for (const handle of windowHandles) { await this.driver.switchTo().window(handle); + const handleTitle = await this.driver.getTitle(); if (handleTitle === title) { return handle; From 36eaaa19ed1ef22f4ef2ce435e27db9191193ae6 Mon Sep 17 00:00:00 2001 From: Vladimir Saric <92527393+VSaric@users.noreply.github.com> Date: Wed, 12 Jul 2023 20:32:46 +0200 Subject: [PATCH 019/172] Added customize tx nonce on ERC20 approve screen when feature is enabled (#17945) --- ui/components/app/app-components.scss | 1 + .../app/custom-nonce/custom-nonce.js | 75 ++++++++++ .../app/custom-nonce/custom-nonce.test.js | 65 +++++++++ ui/components/app/custom-nonce/index.js | 1 + ui/components/app/custom-nonce/index.scss | 15 ++ .../customize-nonce.test.js.snap | 25 ++-- .../customize-nonce.component.js | 39 ++--- .../app/modals/customize-nonce/index.scss | 2 +- ...irm-approve-content.component.test.js.snap | 56 ++++---- .../confirm-approve-content.component.js | 71 +++------- .../confirm-approve-content/index.scss | 27 ---- ui/pages/confirm-approve/confirm-approve.js | 1 + .../token-allowance.test.js.snap | 1 + ui/pages/token-allowance/index.scss | 5 + ui/pages/token-allowance/token-allowance.js | 70 ++++++++- .../token-allowance/token-allowance.test.js | 133 +++++++++++++++++- 16 files changed, 434 insertions(+), 153 deletions(-) create mode 100644 ui/components/app/custom-nonce/custom-nonce.js create mode 100644 ui/components/app/custom-nonce/custom-nonce.test.js create mode 100644 ui/components/app/custom-nonce/index.js create mode 100644 ui/components/app/custom-nonce/index.scss diff --git a/ui/components/app/app-components.scss b/ui/components/app/app-components.scss index 6d3ea4af4..3b748809b 100644 --- a/ui/components/app/app-components.scss +++ b/ui/components/app/app-components.scss @@ -10,6 +10,7 @@ @import 'confirm-page-container/index'; @import 'confirm-data/index'; @import 'confirmation-warning-modal/index'; +@import 'custom-nonce/index'; @import 'nfts-items/index'; @import 'nfts-tab/index'; @import 'nft-details/index'; diff --git a/ui/components/app/custom-nonce/custom-nonce.js b/ui/components/app/custom-nonce/custom-nonce.js new file mode 100644 index 000000000..a7ad0a658 --- /dev/null +++ b/ui/components/app/custom-nonce/custom-nonce.js @@ -0,0 +1,75 @@ +import React, { useContext } from 'react'; +import PropTypes from 'prop-types'; +import { I18nContext } from '../../../../.storybook/i18n'; +import { Box, ButtonLink, Text } from '../../component-library'; +import { + AlignItems, + BorderRadius, + Display, + JustifyContent, + Size, + TextVariant, +} from '../../../helpers/constants/design-system'; + +export default function CustomNonce({ + nextNonce, + customNonceValue, + showCustomizeNonceModal, +}) { + const t = useContext(I18nContext); + + return ( + + + + {t('nonce')} + + showCustomizeNonceModal()} + > + {t('edit')} + + + + {customNonceValue || nextNonce} + + + ); +} + +CustomNonce.propTypes = { + /** + * Getting the next suggested nonce + */ + nextNonce: PropTypes.number, + /** + * Custom nonce value + */ + customNonceValue: PropTypes.string, + /** + * Function that is supposed to open the customized nonce modal + */ + showCustomizeNonceModal: PropTypes.func, +}; diff --git a/ui/components/app/custom-nonce/custom-nonce.test.js b/ui/components/app/custom-nonce/custom-nonce.test.js new file mode 100644 index 000000000..2b8beca85 --- /dev/null +++ b/ui/components/app/custom-nonce/custom-nonce.test.js @@ -0,0 +1,65 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import { fireEvent } from '@testing-library/react'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import CustomNonce from './custom-nonce'; + +describe('CustomNonce', () => { + const store = configureMockStore()({}); + let props = {}; + + beforeEach(() => { + props = { + nextNonce: 1, + customNonceValue: '', + showCustomizeNonceModal: jest.fn(), + }; + }); + + it('should render CustomNonce component header', () => { + const { queryByText } = renderWithProvider( + , + store, + ); + + expect(queryByText('Nonce')).toBeInTheDocument(); + expect(queryByText('Edit')).toBeInTheDocument(); + }); + + it('should render CustomNonce component value when custom nonce value is a empty string', () => { + const { queryByText } = renderWithProvider( + , + store, + ); + + expect(queryByText('Nonce')).toBeInTheDocument(); + expect(queryByText('Edit')).toBeInTheDocument(); + expect(queryByText('1')).toBeInTheDocument(); + }); + + it('should render CustomNonce component value when custom nonce value is edited', () => { + props.customNonceValue = '3'; + const { queryByText } = renderWithProvider( + , + store, + ); + + expect(queryByText('Nonce')).toBeInTheDocument(); + expect(queryByText('Edit')).toBeInTheDocument(); + expect(queryByText('3')).toBeInTheDocument(); + }); + + it('should render CustomNonce component to show customize nonce modal', () => { + const { queryByText, getByText } = renderWithProvider( + , + store, + ); + + const editButton = getByText('Edit'); + expect(queryByText('Nonce')).toBeInTheDocument(); + expect(editButton).toBeInTheDocument(); + expect(queryByText('1')).toBeInTheDocument(); + fireEvent.click(editButton); + expect(props.showCustomizeNonceModal).toHaveBeenCalledTimes(1); + }); +}); diff --git a/ui/components/app/custom-nonce/index.js b/ui/components/app/custom-nonce/index.js new file mode 100644 index 000000000..60b5eedde --- /dev/null +++ b/ui/components/app/custom-nonce/index.js @@ -0,0 +1 @@ +export { default } from './custom-nonce'; diff --git a/ui/components/app/custom-nonce/index.scss b/ui/components/app/custom-nonce/index.scss new file mode 100644 index 000000000..be5994928 --- /dev/null +++ b/ui/components/app/custom-nonce/index.scss @@ -0,0 +1,15 @@ +.custom-nonce { + &__content { + height: 49px; + border: 1px solid var(--color-border-muted); + box-sizing: border-box; + } + + &__header { + flex: 1; + } + + &__value { + flex: 0; + } +} diff --git a/ui/components/app/modals/customize-nonce/__snapshots__/customize-nonce.test.js.snap b/ui/components/app/modals/customize-nonce/__snapshots__/customize-nonce.test.js.snap index b35c12b39..5d05ca908 100644 --- a/ui/components/app/modals/customize-nonce/__snapshots__/customize-nonce.test.js.snap +++ b/ui/components/app/modals/customize-nonce/__snapshots__/customize-nonce.test.js.snap @@ -15,7 +15,7 @@ exports[`Customize Nonce should match snapshot 1`] = ` class="customize-nonce-modal__main-header" >

Edit nonce

@@ -30,14 +30,14 @@ exports[`Customize Nonce should match snapshot 1`] = `
{t('editNonceField')} @@ -68,39 +66,32 @@ const CustomizeNonce = ({
- + {t('editNonceMessage')} - + - - + + {t('editNonceField')} - - +
diff --git a/ui/components/app/modals/customize-nonce/index.scss b/ui/components/app/modals/customize-nonce/index.scss index fb7a5656b..1bd22dc56 100644 --- a/ui/components/app/modals/customize-nonce/index.scss +++ b/ui/components/app/modals/customize-nonce/index.scss @@ -31,7 +31,7 @@ } & &__reset { - @include H7; + @include H6; } &__input { diff --git a/ui/pages/confirm-approve/confirm-approve-content/__snapshots__/confirm-approve-content.component.test.js.snap b/ui/pages/confirm-approve/confirm-approve-content/__snapshots__/confirm-approve-content.component.test.js.snap index 5d1310891..156f69263 100644 --- a/ui/pages/confirm-approve/confirm-approve-content/__snapshots__/confirm-approve-content.component.test.js.snap +++ b/ui/pages/confirm-approve/confirm-approve-content/__snapshots__/confirm-approve-content.component.test.js.snap @@ -129,26 +129,24 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr class="confirm-approve-content__card-content" >
Nonce
- Edit - +
2
@@ -316,26 +314,24 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr class="confirm-approve-content__card-content" >
Nonce
- Edit - +
2
@@ -503,26 +499,24 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr class="confirm-approve-content__card-content" >
Nonce
- Edit - +
2
@@ -690,26 +684,24 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr class="confirm-approve-content__card-content" >
Nonce
- Edit - +
2
diff --git a/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js b/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js index 12f07dd94..b25933c8b 100644 --- a/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js +++ b/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js @@ -14,7 +14,6 @@ import MultiLayerFeeMessage from '../../../components/app/multilayer-fee-message import SecurityProviderBannerMessage from '../../../components/app/security-provider-banner-message/security-provider-banner-message'; import { BLOCK_SIZES, - JustifyContent, DISPLAY, TextColor, IconColor, @@ -38,6 +37,7 @@ import TransactionDetailItem from '../../../components/app/transaction-detail-it import UserPreferencedCurrencyDisplay from '../../../components/app/user-preferenced-currency-display'; import { PRIMARY, SECONDARY } from '../../../helpers/constants/common'; import { ConfirmGasDisplay } from '../../../components/app/confirm-gas-display'; +import CustomNonce from '../../../components/app/custom-nonce'; export default class ConfirmApproveContent extends Component { static contextTypes = { @@ -351,55 +351,6 @@ export default class ConfirmApproveContent extends Component { return null; } - renderCustomNonceContent() { - const { t } = this.context; - const { - useNonceField, - customNonceValue, - updateCustomNonce, - getNextNonce, - nextNonce, - showCustomizeNonceModal, - } = this.props; - return ( - <> - {useNonceField && ( -
- - - {t('nonce')} - - - - - {customNonceValue || nextNonce} - -
- )} - - ); - } - getTokenName() { const { tokenId, assetName, assetStandard, tokenSymbol } = this.props; const { t } = this.context; @@ -586,6 +537,11 @@ export default class ConfirmApproveContent extends Component { userAcknowledgedGasMissing, setUserAcknowledgedGasMissing, renderSimulationFailureWarning, + nextNonce, + getNextNonce, + customNonceValue, + updateCustomNonce, + showCustomizeNonceModal, } = this.props; const { showFullTxDetails, setShowContractDetails } = this.state; @@ -709,7 +665,20 @@ export default class ConfirmApproveContent extends Component { {useNonceField && this.renderApproveContentCard({ showHeader: false, - content: this.renderCustomNonceContent(), + content: ( + { + showCustomizeNonceModal({ + nextNonce, + customNonceValue, + updateCustomNonce, + getNextNonce, + }); + }} + /> + ), useNonceField, noBorder: !showFullTxDetails, footer: ( diff --git a/ui/pages/confirm-approve/confirm-approve-content/index.scss b/ui/pages/confirm-approve/confirm-approve-content/index.scss index 77947c2f7..fe0121301 100644 --- a/ui/pages/confirm-approve/confirm-approve-content/index.scss +++ b/ui/pages/confirm-approve/confirm-approve-content/index.scss @@ -385,33 +385,6 @@ width: 100%; height: 30px; } - - &__custom-nonce-content { - display: flex; - height: 49px; - margin-top: 5px; - margin-bottom: 6px; - padding: 12px 12px 14px 12px; - border: 1px solid var(--color-border-muted); - box-sizing: border-box; - border-radius: 6px; - align-items: center; - } - - &__custom-nonce-header { - flex: 1; - align-items: center; - } - - &__custom-nonce-value { - flex: 0; - } - - & &__custom-nonce-edit { - @include H7; - - width: auto; - } } .confirm-approve-content--full { diff --git a/ui/pages/confirm-approve/confirm-approve.js b/ui/pages/confirm-approve/confirm-approve.js index d0fadc086..0faacf441 100644 --- a/ui/pages/confirm-approve/confirm-approve.js +++ b/ui/pages/confirm-approve/confirm-approve.js @@ -205,6 +205,7 @@ export default function ConfirmApprove({ tokenSymbol={tokenSymbol} decimals={decimals} fromAddressIsLedger={fromAddressIsLedger} + warning={submitWarning} /> {showCustomizeGasPopover && !supportsEIP1559 && (
+
diff --git a/ui/pages/token-allowance/index.scss b/ui/pages/token-allowance/index.scss index 836625da4..1a02474a1 100644 --- a/ui/pages/token-allowance/index.scss +++ b/ui/pages/token-allowance/index.scss @@ -38,4 +38,9 @@ &__full-tx-content { max-width: 100%; } + + &__custom-nonce-warning { + width: 100%; + height: 30px; + } } diff --git a/ui/pages/token-allowance/token-allowance.js b/ui/pages/token-allowance/token-allowance.js index 1186077d8..5ab20f615 100644 --- a/ui/pages/token-allowance/token-allowance.js +++ b/ui/pages/token-allowance/token-allowance.js @@ -1,4 +1,4 @@ -import React, { useState, useContext } from 'react'; +import React, { useState, useContext, useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { useHistory } from 'react-router-dom'; import PropTypes from 'prop-types'; @@ -33,6 +33,8 @@ import { getUnapprovedTransactions, getUseCurrencyRateCheck, getTargetAccountWithSendEtherInfo, + getCustomNonceValue, + getNextSuggestedNonce, } from '../../selectors'; import { NETWORK_TO_NAME_MAP } from '../../../shared/constants/network'; import { @@ -40,6 +42,7 @@ import { cancelTxs, showModal, updateAndApproveTx, + getNextNonce, updateCustomNonce, } from '../../store/actions'; import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck'; @@ -63,6 +66,8 @@ import SimulationErrorMessage from '../../components/ui/simulation-error-message import LedgerInstructionField from '../../components/app/ledger-instruction-field/ledger-instruction-field'; import SecurityProviderBannerMessage from '../../components/app/security-provider-banner-message/security-provider-banner-message'; import { Text, Icon, IconName } from '../../components/component-library'; +import { ConfirmPageContainerWarning } from '../../components/app/confirm-page-container/confirm-page-container-content'; +import CustomNonce from '../../components/app/custom-nonce'; const ALLOWED_HOSTS = ['portfolio.metamask.io']; @@ -91,6 +96,7 @@ export default function TokenAllowance({ toAddress, tokenSymbol, fromAddressIsLedger, + warning, }) { const t = useContext(I18nContext); const dispatch = useDispatch(); @@ -124,6 +130,8 @@ export default function TokenAllowance({ const unapprovedTxCount = useSelector(getUnapprovedTxCount); const unapprovedTxs = useSelector(getUnapprovedTransactions); const useCurrencyRateCheck = useSelector(getUseCurrencyRateCheck); + const nextNonce = useSelector(getNextSuggestedNonce); + const customNonceValue = useSelector(getCustomNonceValue); const replaceCommaToDot = (inputValue) => { return inputValue.replace(/,/gu, '.'); @@ -175,7 +183,6 @@ export default function TokenAllowance({ const networkName = NETWORK_TO_NAME_MAP[fullTxData.chainId] || networkIdentifier; - const customNonceValue = ''; const customNonceMerge = (transactionData) => customNonceValue ? { @@ -253,6 +260,39 @@ export default function TokenAllowance({ ); }; + const handleNextNonce = () => { + dispatch(getNextNonce()); + }; + + useEffect(() => { + handleNextNonce(); + }, [dispatch]); + + const handleUpdateCustomNonce = (value) => { + dispatch(updateCustomNonce(value)); + }; + + const handleCustomizeNonceModal = ( + /* eslint-disable no-shadow */ + useNonceField, + nextNonce, + customNonceValue, + updateCustomNonce, + getNextNonce, + /* eslint-disable no-shadow */ + ) => { + dispatch( + showModal({ + name: 'CUSTOMIZE_NONCE', + useNonceField, + nextNonce, + customNonceValue, + updateCustomNonce, + getNextNonce, + }), + ); + }; + const isEmpty = customSpendingCap === ''; const renderContractTokenValues = ( @@ -317,6 +357,11 @@ export default function TokenAllowance({ accountAddress={userAddress} chainId={fullTxData.chainId} /> + {warning && ( + + + + )} )} + {useNonceField && ( + + + handleCustomizeNonceModal( + useNonceField, + nextNonce, + customNonceValue, + handleUpdateCustomNonce, + handleNextNonce, + ) + } + /> + + )} ({ disconnectGasFeeEstimatePoller: jest.fn(), getGasFeeTimeEstimate: jest.fn().mockImplementation(() => Promise.resolve()), @@ -99,6 +104,8 @@ jest.mock('../../store/actions', () => ({ updateTransactionGasFees: () => ({ type: 'UPDATE_TRANSACTION_PARAMS' }), updatePreviousGasParams: () => ({ type: 'UPDATE_TRANSACTION_PARAMS' }), createTransactionEventFragment: jest.fn(), + getNextNonce: () => jest.fn(), + showModal: () => mockShowModal, updateCustomNonce: () => ({ type: 'UPDATE_TRANSACTION_PARAMS' }), estimateGas: jest.fn().mockImplementation(() => Promise.resolve()), })); @@ -146,6 +153,8 @@ describe('TokenAllowancePage', () => { currentTokenBalance: '10', toAddress: '0x9bc5baf874d2da8d216ae9f137804184ee5afef4', tokenSymbol: 'TST', + showCustomizeGasModal: jest.fn(), + warning: '', txData: { id: 3049568294499567, time: 1664449552289, @@ -184,7 +193,7 @@ describe('TokenAllowancePage', () => { let store; beforeEach(() => { - store = configureMockStore()(state); + store = configureMockStore([thunk])(state); }); it('should match snapshot', () => { @@ -212,6 +221,126 @@ describe('TokenAllowancePage', () => { expect(onCloseBtn).toBeInTheDocument(); }); + it('should not render customize nonce modal if useNonceField is set to false', () => { + const { queryByText } = renderWithProvider( + , + store, + ); + expect(queryByText('Nonce')).not.toBeInTheDocument(); + expect(queryByText('1')).not.toBeInTheDocument(); + expect(mockShowModal).not.toHaveBeenCalledTimes(1); + }); + + it('should render customize nonce modal if useNonceField is set to true', () => { + props.useNonceField = true; + props.nextNonce = 1; + const { queryByText, getByText } = renderWithProvider( + , + store, + ); + const editButton = getByText('Edit'); + expect(queryByText('Nonce')).toBeInTheDocument(); + expect(queryByText('1')).toBeInTheDocument(); + fireEvent.click(editButton); + expect(mockShowModal).toHaveBeenCalledTimes(1); + }); + + it('should render nextNonce value when custom nonce value is a empty string', () => { + props.useNonceField = true; + props.customNonceValue = ''; + const { queryByText, getByText } = renderWithProvider( + , + store, + ); + const editButton = getByText('Edit'); + expect(queryByText('Nonce')).toBeInTheDocument(); + expect(queryByText('1')).toBeInTheDocument(); + fireEvent.click(editButton); + expect(mockShowModal).toHaveBeenCalledTimes(2); + }); + + it('should render edited custom nonce value', () => { + props.useNonceField = true; + state.metamask.customNonceValue = '3'; + const { queryByText, getByText } = renderWithProvider( + , + store, + ); + const editButton = getByText('Edit'); + expect(queryByText('Nonce')).toBeInTheDocument(); + expect(queryByText('3')).toBeInTheDocument(); + fireEvent.click(editButton); + expect(mockShowModal).toHaveBeenCalledTimes(3); + }); + + it('should render customize nonce warning if custom nonce value is higher than nextNonce value', () => { + props.useNonceField = true; + props.nextNonce = 2; + props.customNonceValue = '3'; + props.warning = 'Nonce is higher than suggested nonce of 2'; + const { getByText } = renderWithProvider( + , + store, + ); + expect( + getByText('Nonce is higher than suggested nonce of 2'), + ).toBeInTheDocument(); + }); + + it('should not render customize nonce warning if custom nonce value is lower than nextNonce value', () => { + props.useNonceField = true; + props.nextNonce = 2; + props.customNonceValue = '1'; + props.warning = ''; + const { container } = renderWithProvider( + , + store, + ); + const customizeNonceWarning = container.querySelector( + '.token-allowance-container__custom-nonce-warning', + ); + expect(customizeNonceWarning).not.toBeInTheDocument(); + }); + + it('should render customize nonce modal when next button is clicked and if useNonceField is set to true', () => { + props.useNonceField = true; + state.metamask.customNonceValue = '2'; + const { getByText, getAllByText, queryByText } = renderWithProvider( + , + store, + ); + + const nextButton = getByText('Next'); + fireEvent.click(nextButton); + + const editButton = getAllByText('Edit'); + expect(queryByText('Nonce')).toBeInTheDocument(); + expect(queryByText('2')).toBeInTheDocument(); + fireEvent.click(editButton[1]); + expect(mockShowModal).toHaveBeenCalledTimes(4); + }); + + it('should render customize nonce modal when next button is clicked, than back button is clicked, than return to previous page and if useNonceField is set to true', () => { + props.useNonceField = true; + state.metamask.customNonceValue = '2'; + const { getByText, queryByText } = renderWithProvider( + , + store, + ); + + const nextButton = getByText('Next'); + fireEvent.click(nextButton); + + const backButton = getByText('< Back'); + fireEvent.click(backButton); + + const editButton = getByText('Edit'); + expect(queryByText('Nonce')).toBeInTheDocument(); + expect(queryByText('2')).toBeInTheDocument(); + fireEvent.click(editButton); + expect(mockShowModal).toHaveBeenCalledTimes(5); + }); + it('should click View details and show function type', () => { const { getByText } = renderWithProvider( , @@ -353,7 +482,7 @@ describe('TokenAllowancePage', () => { selectedAddress: '0xc42edfcc21ed14dda456aa0756c153f7985d8813', }, }; - const newStore = configureMockStore()(newState); + const newStore = configureMockStore([thunk])(newState); const { queryByText } = renderWithProvider( , newStore, From d1d39ee1cd6e89c9400d9bd986b8db0db99f116f Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 12 Jul 2023 19:10:01 -0230 Subject: [PATCH 020/172] Fix unit test failures (#19983) * Fix unit test failures Fix unit test failures by updating Jest snapshots * Update additional outdated snapshot --- .../__snapshots__/customize-nonce.test.js.snap | 4 ++-- .../confirm-approve-content.component.test.js.snap | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ui/components/app/modals/customize-nonce/__snapshots__/customize-nonce.test.js.snap b/ui/components/app/modals/customize-nonce/__snapshots__/customize-nonce.test.js.snap index 5d05ca908..bfa567807 100644 --- a/ui/components/app/modals/customize-nonce/__snapshots__/customize-nonce.test.js.snap +++ b/ui/components/app/modals/customize-nonce/__snapshots__/customize-nonce.test.js.snap @@ -37,7 +37,7 @@ exports[`Customize Nonce should match snapshot 1`] = ` > This is an advanced feature, use cautiously. @@ -325,7 +325,7 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr Nonce @@ -510,7 +510,7 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr Nonce @@ -695,7 +695,7 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr Nonce From 7ef2730c9a585c4addfeb9d9cb225794578d932e Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 12 Jul 2023 19:50:31 -0230 Subject: [PATCH 021/172] Fix preview builds on CI (#19970) Preview builds were setup to install correctly on CircleCI prior to the Yarn v3 upgrade, but that integration broke with that upgrade. The Yarn and CircleCI configuration has been updated to fix this. The `.yarnrc.yaml` file has been updated to configure the GitHub registry but leave it disabled by default. It can be enabled dynamically using an environment variable. This lets us switch between registries without updating the file. The new workflow is documented here: https://github.com/MetaMask/core/pull/1481 --- .circleci/config.yml | 10 ++++------ .yarnrc.yml | 9 +++++++++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a8522d1ad..e8b002718 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -353,17 +353,15 @@ jobs: echo "Not a PR; skipping" fi - run: - name: Setup registry config for using package previews on draft PRs + name: Install dependencies command: | if [[ $IS_DRAFT == 'true' ]] then - printf '%s\n\n%s' '@metamask:registry=https://npm.pkg.github.com' "//npm.pkg.github.com/:_authToken=${GITHUB_PACKAGE_READ_TOKEN}" > .npmrc + # Use GitHub registry on draft PRs, allowing the use of preview builds + METAMASK_NPM_REGISTRY=https://npm.pkg.github.com yarn --immutable else - echo "Not draft; skipping GitHub registry setup" + yarn --immutable fi - - run: - name: Install deps - command: yarn --immutable - save_cache: key: dependency-cache-v1-{{ checksum "yarn.lock" }} paths: diff --git a/.yarnrc.yml b/.yarnrc.yml index 5d351f8e2..03fa25aa0 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -8,6 +8,15 @@ logFilters: nodeLinker: node-modules +npmRegistries: + "https://npm.pkg.github.com": + npmAlwaysAuth: true + npmAuthToken: "${GITHUB_PACKAGE_READ_TOKEN-}" + +npmScopes: + metamask: + npmRegistryServer: "${METAMASK_NPM_REGISTRY:-https://registry.yarnpkg.com}" + plugins: - path: .yarn/plugins/@yarnpkg/plugin-allow-scripts.cjs spec: "https://raw.githubusercontent.com/LavaMoat/LavaMoat/main/packages/yarn-plugin-allow-scripts/bundles/@yarnpkg/plugin-allow-scripts.js" From 70dd9a02542f311b32511196d6ec56e4f6b1c4ea Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 12 Jul 2023 20:05:27 -0230 Subject: [PATCH 022/172] Prevent controller events from crashing (#19963) * Prevent controller events from crashing The package `@metamask/base-controller` has been updated to v3.1, which includes a change to how event subscriber errors are handled. Errors thrown in event subscribers will no longer interrupt event publishing. Subscriber errors are caught and thrown in a timeout handler, ensuring that they are logged and captured by Sentry. We can find any subscriber errors by looking at the background console, or at the Sentry dashboard. Fixes #19801 * Update LavaMoat policies --------- Co-authored-by: MetaMask Bot --- lavamoat/browserify/beta/policy.json | 3 +++ lavamoat/browserify/desktop/policy.json | 3 +++ lavamoat/browserify/flask/policy.json | 3 +++ lavamoat/browserify/main/policy.json | 3 +++ lavamoat/browserify/mmi/policy.json | 3 +++ package.json | 2 +- yarn.lock | 10 +++++----- 7 files changed, 21 insertions(+), 6 deletions(-) diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index 24f626987..d0c93d301 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -858,6 +858,9 @@ } }, "@metamask/base-controller": { + "globals": { + "setTimeout": true + }, "packages": { "immer": true } diff --git a/lavamoat/browserify/desktop/policy.json b/lavamoat/browserify/desktop/policy.json index 1ff496ed2..b1bdba0e4 100644 --- a/lavamoat/browserify/desktop/policy.json +++ b/lavamoat/browserify/desktop/policy.json @@ -858,6 +858,9 @@ } }, "@metamask/base-controller": { + "globals": { + "setTimeout": true + }, "packages": { "immer": true } diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index 1ff496ed2..b1bdba0e4 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -858,6 +858,9 @@ } }, "@metamask/base-controller": { + "globals": { + "setTimeout": true + }, "packages": { "immer": true } diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index 24f626987..d0c93d301 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -858,6 +858,9 @@ } }, "@metamask/base-controller": { + "globals": { + "setTimeout": true + }, "packages": { "immer": true } diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index 46ea1ba04..38dee29d1 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -1079,6 +1079,9 @@ } }, "@metamask/base-controller": { + "globals": { + "setTimeout": true + }, "packages": { "immer": true } diff --git a/package.json b/package.json index 4abcb2bf1..d30a20466 100644 --- a/package.json +++ b/package.json @@ -228,7 +228,7 @@ "@metamask/announcement-controller": "^4.0.0", "@metamask/approval-controller": "^3.4.0", "@metamask/assets-controllers": "^9.2.0", - "@metamask/base-controller": "^3.0.0", + "@metamask/base-controller": "^3.1.0", "@metamask/browser-passworder": "^4.1.0", "@metamask/contract-metadata": "^2.3.1", "@metamask/controller-utils": "^4.1.0", diff --git a/yarn.lock b/yarn.lock index 4db3f92c8..6914e07bd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3947,13 +3947,13 @@ __metadata: languageName: node linkType: hard -"@metamask/base-controller@npm:^3.0.0": - version: 3.0.0 - resolution: "@metamask/base-controller@npm:3.0.0" +"@metamask/base-controller@npm:^3.0.0, @metamask/base-controller@npm:^3.1.0": + version: 3.1.0 + resolution: "@metamask/base-controller@npm:3.1.0" dependencies: "@metamask/utils": ^5.0.2 immer: ^9.0.6 - checksum: a0853d90b024466c4108531cbf4459bd2f66fa6e0b912e42bd27cdf54262411a5601117649b6061424475ffa6b9714c5199d686c21e4d07c3b7b1ee0b4c17caa + checksum: fc1597a099e6d28bd089df936ca349d6c38c2e1b0f0737385cba30c34a5239241519eb172d77c70f8db2604f4dc5724f6893affe42bdd104cef98f9cfd6f1db8 languageName: node linkType: hard @@ -24636,7 +24636,7 @@ __metadata: "@metamask/approval-controller": ^3.4.0 "@metamask/assets-controllers": ^9.2.0 "@metamask/auto-changelog": ^2.1.0 - "@metamask/base-controller": ^3.0.0 + "@metamask/base-controller": ^3.1.0 "@metamask/browser-passworder": ^4.1.0 "@metamask/contract-metadata": ^2.3.1 "@metamask/controller-utils": ^4.1.0 From 4e89c6ca8c623533d55bab4fc21148a28e358171 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 12 Jul 2023 20:05:57 -0230 Subject: [PATCH 023/172] Prevent controller events from crashing (#19963) * Prevent controller events from crashing The package `@metamask/base-controller` has been updated to v3.1, which includes a change to how event subscriber errors are handled. Errors thrown in event subscribers will no longer interrupt event publishing. Subscriber errors are caught and thrown in a timeout handler, ensuring that they are logged and captured by Sentry. We can find any subscriber errors by looking at the background console, or at the Sentry dashboard. Fixes #19801 * Update LavaMoat policies --------- Co-authored-by: MetaMask Bot From b5ece42ca1aec91215651b5debc3e853e8f535b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Oliv=C3=A9?= Date: Thu, 13 Jul 2023 10:42:08 +0200 Subject: [PATCH 024/172] [MMI] Fix Connect MMI and Deep link Flows (#19881) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Sending showCustodyConfirmLink as a prop and fixing other issues * Upgraded MMI extension monrepo and trying to fix the issue * prevents deeplink from closing * Fixed styles of Custody view and changed the place of it * Fixed CI issues * fixing eslint issues * Update LavaMoat policies * fixing tests * Fixed test * updated snapshots * reorder, otherwise it won't make sense * adds necessary methods * removes duplicated key value * updated snapshot --------- Co-authored-by: Antonio Regadas Co-authored-by: MetaMask Bot Co-authored-by: António Regadas --- app/_locales/en/messages.json | 6 + lavamoat/browserify/mmi/policy.json | 9 +- package.json | 2 +- ...onfirm-page-container-content.component.js | 3 +- .../signature-request-original.container.js | 120 +++++++++++------- .../signature-request.container.js | 118 ++++++++++------- .../confirm-transaction-base.component.js | 10 +- .../confirm-transaction-base.container.js | 11 +- .../confirm-transaction-base.test.js | 2 +- .../create-account.component.js | 16 +-- ui/pages/home/home.container.js | 3 +- .../confirm-add-custodian-token.js | 24 ++-- .../confirm-add-custodian-token.test.js | 10 ++ .../__snapshots__/custody.test.js.snap | 111 ++++++++-------- ui/pages/institutional/custody/custody.js | 64 +++++----- ui/pages/routes/routes.component.js | 7 + ui/store/actions.ts | 3 +- .../institutional/institution-actions.test.js | 7 +- ui/store/institutional/institution-actions.ts | 17 ++- .../institutional/institution-background.ts | 15 +-- yarn.lock | 77 ++++++----- 21 files changed, 361 insertions(+), 274 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 39d8216b7..dac6a5634 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -982,6 +982,12 @@ "custodianAccount": { "message": "Custodian account" }, + "custodianAccountAddedDesc": { + "message": "You can now use your custodian accounts in MetaMask Institutional." + }, + "custodianAccountAddedTitle": { + "message": "Selected custodian accounts have been added." + }, "custodianReplaceRefreshTokenChangedFailed": { "message": "Please go to $1 and click the 'Connect to MMI' button within their user interface to connect your accounts to MMI again." }, diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index 38dee29d1..c2c8c36c1 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -815,11 +815,18 @@ }, "packages": { "@ethereumjs/tx>@ethereumjs/util": true, - "@metamask-institutional/custody-controller": true, + "@metamask-institutional/extension>@metamask-institutional/custody-controller": true, "@metamask-institutional/sdk": true, "@metamask-institutional/sdk>@metamask-institutional/types": true } }, + "@metamask-institutional/extension>@metamask-institutional/custody-controller": { + "packages": { + "@ethereumjs/tx>@ethereumjs/util": true, + "@metamask-institutional/custody-keyring": true, + "@metamask/obs-store": true + } + }, "@metamask-institutional/institutional-features": { "globals": { "chrome.runtime.id": true, diff --git a/package.json b/package.json index d30a20466..177ee5369 100644 --- a/package.json +++ b/package.json @@ -218,7 +218,7 @@ "@material-ui/core": "^4.11.0", "@metamask-institutional/custody-controller": "0.2.6", "@metamask-institutional/custody-keyring": "^0.0.25", - "@metamask-institutional/extension": "^0.1.3", + "@metamask-institutional/extension": "^0.1.6", "@metamask-institutional/institutional-features": "^1.1.8", "@metamask-institutional/portfolio-dashboard": "^1.1.3", "@metamask-institutional/rpc-allowlist": "^1.0.0", diff --git a/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js index 713cd9293..c4d907462 100644 --- a/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js +++ b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js @@ -123,9 +123,10 @@ export default class ConfirmPageContainerContent extends Component { ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) noteComponent && ( { this.context.trackEvent({ category: 'Note to trader', diff --git a/ui/components/app/signature-request-original/signature-request-original.container.js b/ui/components/app/signature-request-original/signature-request-original.container.js index 242ace8f8..b0f5e3171 100644 --- a/ui/components/app/signature-request-original/signature-request-original.container.js +++ b/ui/components/app/signature-request-original/signature-request-original.container.js @@ -17,7 +17,10 @@ import { setPersonalMessageInProgress, } from '../../../store/institutional/institution-background'; import { getEnvironmentType } from '../../../../app/scripts/lib/util'; -import { checkForUnapprovedMessages } from '../../../store/institutional/institution-actions'; +import { + showCustodyConfirmLink, + checkForUnapprovedMessages, +} from '../../../store/institutional/institution-actions'; import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app'; ///: END:ONLY_INCLUDE_IN import { @@ -75,52 +78,6 @@ function mapStateToProps(state, ownProps) { let mapDispatchToProps = null; -///: BEGIN:ONLY_INCLUDE_IN(build-mmi) -function mmiMapDispatchToProps(dispatch) { - const mmiActions = mmiActionsFactory(); - return { - clearConfirmTransaction: () => dispatch(clearConfirmTransaction()), - setMsgInProgress: (msgId) => dispatch(setPersonalMessageInProgress(msgId)), - showCustodianDeepLink: ({ - custodyId, - fromAddress, - closeNotification, - onDeepLinkFetched, - onDeepLinkShown, - }) => - showCustodianDeepLink({ - dispatch, - mmiActions, - txId: undefined, - fromAddress, - custodyId, - isSignature: true, - closeNotification, - onDeepLinkFetched, - onDeepLinkShown, - }), - showTransactionsFailedModal: ({ - errorMessage, - closeNotification, - operationFailed, - }) => - dispatch( - showModal({ - name: 'TRANSACTION_FAILED', - errorMessage, - closeNotification, - operationFailed, - }), - ), - setWaitForConfirmDeepLinkDialog: (wait) => - dispatch(mmiActions.setWaitForConfirmDeepLinkDialog(wait)), - goHome: () => dispatch(goHome()), - }; -} - -mapDispatchToProps = mmiMapDispatchToProps; -///: END:ONLY_INCLUDE_IN - mapDispatchToProps = function (dispatch) { return { goHome: () => dispatch(goHome()), @@ -150,6 +107,75 @@ mapDispatchToProps = function (dispatch) { }; }; +///: BEGIN:ONLY_INCLUDE_IN(build-mmi) +function mmiMapDispatchToProps(dispatch) { + const mmiActions = mmiActionsFactory(); + return { + setMsgInProgress: (msgId) => dispatch(setPersonalMessageInProgress(msgId)), + showCustodianDeepLink: ({ + custodyId, + fromAddress, + closeNotification, + onDeepLinkFetched, + onDeepLinkShown, + }) => + showCustodianDeepLink({ + dispatch, + mmiActions, + txId: undefined, + fromAddress, + custodyId, + isSignature: true, + closeNotification, + onDeepLinkFetched, + onDeepLinkShown, + showCustodyConfirmLink, + }), + showTransactionsFailedModal: ({ + errorMessage, + closeNotification, + operationFailed, + }) => + dispatch( + showModal({ + name: 'TRANSACTION_FAILED', + errorMessage, + closeNotification, + operationFailed, + }), + ), + setWaitForConfirmDeepLinkDialog: (wait) => + dispatch(mmiActions.setWaitForConfirmDeepLinkDialog(wait)), + goHome: () => dispatch(goHome()), + clearConfirmTransaction: () => dispatch(clearConfirmTransaction()), + showRejectTransactionsConfirmationModal: ({ + onSubmit, + unapprovedTxCount: messagesCount, + }) => { + return dispatch( + showModal({ + name: 'REJECT_TRANSACTIONS', + onSubmit, + unapprovedTxCount: messagesCount, + isRequestType: true, + }), + ); + }, + completedTx: (txId) => dispatch(completedTx(txId)), + resolvePendingApproval: (id) => { + dispatch(resolvePendingApproval(id)); + }, + rejectPendingApproval: (id, error) => + dispatch(rejectPendingApproval(id, error)), + cancelAllApprovals: (messagesList) => { + dispatch(rejectAllMessages(messagesList)); + }, + }; +} + +mapDispatchToProps = mmiMapDispatchToProps; +///: END:ONLY_INCLUDE_IN + function mergeProps(stateProps, dispatchProps, ownProps) { const { txData } = ownProps; diff --git a/ui/components/app/signature-request/signature-request.container.js b/ui/components/app/signature-request/signature-request.container.js index f6f3e8fea..4653a972c 100644 --- a/ui/components/app/signature-request/signature-request.container.js +++ b/ui/components/app/signature-request/signature-request.container.js @@ -30,7 +30,10 @@ import { setTypedMessageInProgress, } from '../../../store/institutional/institution-background'; import { getEnvironmentType } from '../../../../app/scripts/lib/util'; -import { checkForUnapprovedMessages } from '../../../store/institutional/institution-actions'; +import { + showCustodyConfirmLink, + checkForUnapprovedMessages, +} from '../../../store/institutional/institution-actions'; ///: END:ONLY_INCLUDE_IN import { ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) @@ -101,52 +104,6 @@ function mapStateToProps(state, ownProps) { let mapDispatchToProps = null; -///: BEGIN:ONLY_INCLUDE_IN(build-mmi) -function mmiMapDispatchToProps(dispatch) { - const mmiActions = mmiActionsFactory(); - return { - clearConfirmTransaction: () => dispatch(clearConfirmTransaction()), - setMsgInProgress: (msgId) => dispatch(setTypedMessageInProgress(msgId)), - showCustodianDeepLink: ({ - custodyId, - fromAddress, - closeNotification, - onDeepLinkFetched, - onDeepLinkShown, - }) => - showCustodianDeepLink({ - dispatch, - mmiActions, - txId: undefined, - fromAddress, - custodyId, - isSignature: true, - closeNotification, - onDeepLinkFetched, - onDeepLinkShown, - }), - showTransactionsFailedModal: ({ - errorMessage, - closeNotification, - operationFailed, - }) => - dispatch( - showModal({ - name: 'TRANSACTION_FAILED', - errorMessage, - closeNotification, - operationFailed, - }), - ), - setWaitForConfirmDeepLinkDialog: (wait) => - dispatch(mmiActions.setWaitForConfirmDeepLinkDialog(wait)), - goHome: () => dispatch(goHome()), - }; -} - -mapDispatchToProps = mmiMapDispatchToProps; -///: END:ONLY_INCLUDE_IN - mapDispatchToProps = function (dispatch) { return { resolvePendingApproval: (id) => dispatch(resolvePendingApproval(id)), @@ -173,6 +130,73 @@ mapDispatchToProps = function (dispatch) { }; }; +///: BEGIN:ONLY_INCLUDE_IN(build-mmi) +function mmiMapDispatchToProps(dispatch) { + const mmiActions = mmiActionsFactory(); + return { + setMsgInProgress: (msgId) => dispatch(setTypedMessageInProgress(msgId)), + showCustodianDeepLink: ({ + custodyId, + fromAddress, + closeNotification, + onDeepLinkFetched, + onDeepLinkShown, + }) => + showCustodianDeepLink({ + dispatch, + mmiActions, + txId: undefined, + fromAddress, + custodyId, + isSignature: true, + closeNotification, + onDeepLinkFetched, + onDeepLinkShown, + showCustodyConfirmLink, + }), + showTransactionsFailedModal: ({ + errorMessage, + closeNotification, + operationFailed, + }) => + dispatch( + showModal({ + name: 'TRANSACTION_FAILED', + errorMessage, + closeNotification, + operationFailed, + }), + ), + setWaitForConfirmDeepLinkDialog: (wait) => + dispatch(mmiActions.setWaitForConfirmDeepLinkDialog(wait)), + goHome: () => dispatch(goHome()), + resolvePendingApproval: (id) => dispatch(resolvePendingApproval(id)), + completedTx: (id) => dispatch(completedTx(id)), + rejectPendingApproval: (id, error) => + dispatch(rejectPendingApproval(id, error)), + clearConfirmTransaction: () => dispatch(clearConfirmTransaction()), + showRejectTransactionsConfirmationModal: ({ + onSubmit, + unapprovedTxCount: unapprovedMessagesCount, + }) => { + return dispatch( + showModal({ + name: 'REJECT_TRANSACTIONS', + onSubmit, + unapprovedTxCount: unapprovedMessagesCount, + isRequestType: true, + }), + ); + }, + cancelAllApprovals: (unconfirmedMessagesList) => { + dispatch(rejectAllMessages(unconfirmedMessagesList)); + }, + }; +} + +mapDispatchToProps = mmiMapDispatchToProps; +///: END:ONLY_INCLUDE_IN + function mergeProps(stateProps, dispatchProps, ownProps) { const { allAccounts, diff --git a/ui/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/pages/confirm-transaction-base/confirm-transaction-base.component.js index 6412a9c0d..82b98637f 100644 --- a/ui/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -581,7 +581,7 @@ export default class ConfirmTransactionBase extends Component { }); } - handleCancel() { + async handleCancel() { const { txData, cancelTransaction, @@ -592,9 +592,8 @@ export default class ConfirmTransactionBase extends Component { this._removeBeforeUnload(); updateCustomNonce(''); - cancelTransaction(txData).then(() => { - history.push(mostRecentOverviewPage); - }); + await cancelTransaction(txData); + history.push(mostRecentOverviewPage); } handleSubmit() { @@ -705,6 +704,7 @@ export default class ConfirmTransactionBase extends Component { toAccounts, toAddress, showCustodianDeepLink, + clearConfirmTransaction, } = this.props; const { noteText } = this.state; @@ -761,7 +761,7 @@ export default class ConfirmTransactionBase extends Component { }); }, onDeepLinkShown: () => { - this.props.clearConfirmTransaction(); + clearConfirmTransaction(); this.setState({ submitting: false }, () => { history.push(mostRecentOverviewPage); updateCustomNonce(''); diff --git a/ui/pages/confirm-transaction-base/confirm-transaction-base.container.js b/ui/pages/confirm-transaction-base/confirm-transaction-base.container.js index 2518e3ee6..daf9e10ff 100644 --- a/ui/pages/confirm-transaction-base/confirm-transaction-base.container.js +++ b/ui/pages/confirm-transaction-base/confirm-transaction-base.container.js @@ -76,6 +76,7 @@ import { CUSTOM_GAS_ESTIMATE } from '../../../shared/constants/gas'; import { getAccountType } from '../../selectors/selectors'; import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../shared/constants/app'; import { getIsNoteToTraderSupported } from '../../selectors/institutional/selectors'; +import { showCustodyConfirmLink } from '../../store/institutional/institution-actions'; ///: END:ONLY_INCLUDE_IN import { TransactionStatus, @@ -330,15 +331,6 @@ export const mapDispatchToProps = (dispatch) => { ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) getCustodianConfirmDeepLink: (id) => dispatch(mmiActions.getCustodianConfirmDeepLink(id)), - showCustodyConfirmLink: ({ link, address, closeNotification, custodyId }) => - dispatch( - mmiActions.showCustodyConfirmLink({ - link, - address, - closeNotification, - custodyId, - }), - ), showTransactionsFailedModal: (errorMessage, closeNotification) => dispatch( showModal({ @@ -362,6 +354,7 @@ export const mapDispatchToProps = (dispatch) => { closeNotification, onDeepLinkFetched, onDeepLinkShown, + showCustodyConfirmLink, }), setWaitForConfirmDeepLinkDialog: (wait) => dispatch(mmiActions.setWaitForConfirmDeepLinkDialog(wait)), diff --git a/ui/pages/confirm-transaction-base/confirm-transaction-base.test.js b/ui/pages/confirm-transaction-base/confirm-transaction-base.test.js index bc0ac5dff..7a079ece4 100644 --- a/ui/pages/confirm-transaction-base/confirm-transaction-base.test.js +++ b/ui/pages/confirm-transaction-base/confirm-transaction-base.test.js @@ -234,7 +234,7 @@ describe('Confirm Transaction Base', () => { store, ); - expect(getByTestId('transaction-note')).toBeInTheDocument(); + expect(getByTestId('note-tab')).toBeInTheDocument(); }); it('handleMainSubmit calls sendTransaction correctly', async () => { diff --git a/ui/pages/create-account/create-account.component.js b/ui/pages/create-account/create-account.component.js index 789ebb42f..e25d95800 100644 --- a/ui/pages/create-account/create-account.component.js +++ b/ui/pages/create-account/create-account.component.js @@ -1,16 +1,7 @@ import React from 'react'; import { Route, Switch } from 'react-router-dom'; import Box from '../../components/ui/box'; - -import { - CONNECT_HARDWARE_ROUTE, - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - CUSTODY_ACCOUNT_ROUTE, - ///: END:ONLY_INCLUDE_IN -} from '../../helpers/constants/routes'; -///: BEGIN:ONLY_INCLUDE_IN(build-mmi) -import CustodyPage from '../institutional/custody'; -///: END:ONLY_INCLUDE_IN +import { CONNECT_HARDWARE_ROUTE } from '../../helpers/constants/routes'; import ConnectHardwareForm from './connect-hardware'; export default function CreateAccountPage() { @@ -22,11 +13,6 @@ export default function CreateAccountPage() { path={CONNECT_HARDWARE_ROUTE} component={ConnectHardwareForm} /> - { - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - - ///: END:ONLY_INCLUDE_IN - } ); diff --git a/ui/pages/home/home.container.js b/ui/pages/home/home.container.js index 1fe1a47f7..792d2b494 100644 --- a/ui/pages/home/home.container.js +++ b/ui/pages/home/home.container.js @@ -138,7 +138,8 @@ const mapStateToProps = (state) => { selectedAddress, firstPermissionsRequestId, totalUnapprovedCount, - hasApprovalFlows: getApprovalFlows(state).length > 0, + hasApprovalFlows: + Array.isArray(getApprovalFlows) && getApprovalFlows(state).length > 0, connectedStatusPopoverHasBeenShown, defaultHomeActiveTabName, firstTimeFlowType, diff --git a/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.js b/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.js index e353f2285..49f81e492 100644 --- a/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.js +++ b/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.js @@ -168,11 +168,13 @@ const ConfirmAddCustodianToken = () => { size={BUTTON_SIZES.LG} data-testid="cancel-btn" onClick={async () => { - await mmiActions.removeAddTokenConnectRequest({ - origin: connectRequest.origin, - apiUrl: connectRequest.apiUrl, - token: connectRequest.token, - }); + await dispatch( + mmiActions.removeAddTokenConnectRequest({ + origin: connectRequest.origin, + apiUrl: connectRequest.apiUrl, + token: connectRequest.token, + }), + ); trackEvent({ category: 'MMI', @@ -220,11 +222,13 @@ const ConfirmAddCustodianToken = () => { }), ); - await mmiActions.removeAddTokenConnectRequest({ - origin: connectRequest.origin, - apiUrl: connectRequest.apiUrl, - token: connectRequest.token, - }); + await dispatch( + mmiActions.removeAddTokenConnectRequest({ + origin: connectRequest.origin, + apiUrl: connectRequest.apiUrl, + token: connectRequest.token, + }), + ); trackEvent({ category: 'MMI', diff --git a/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.test.js b/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.test.js index 4f4b75690..262d46b16 100644 --- a/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.test.js +++ b/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.test.js @@ -4,6 +4,16 @@ import configureMockStore from 'redux-mock-store'; import { renderWithProvider } from '../../../../test/lib/render-helpers'; import ConfirmAddCustodianToken from './confirm-add-custodian-token'; +const mockedRemoveAddTokenConnectRequest = jest + .fn() + .mockReturnValue({ type: 'TYPE' }); + +jest.mock('../../../store/institutional/institution-background', () => ({ + mmiActionsFactory: () => ({ + removeAddTokenConnectRequest: mockedRemoveAddTokenConnectRequest, + }), +})); + describe('Confirm Add Custodian Token', () => { const mockStore = { metamask: { diff --git a/ui/pages/institutional/custody/__snapshots__/custody.test.js.snap b/ui/pages/institutional/custody/__snapshots__/custody.test.js.snap index a51b3ea52..83e74b31a 100644 --- a/ui/pages/institutional/custody/__snapshots__/custody.test.js.snap +++ b/ui/pages/institutional/custody/__snapshots__/custody.test.js.snap @@ -20,72 +20,75 @@ exports[`CustodyPage renders CustodyPage 1`] = ` exports[`CustodyPage renders CustodyPage 2`] = `
- -
+ +
- -

+ + +

+ Back +

+
+

- Back -

-

-

- Custodial Accounts -

-
- Please choose the custodian you want to connect in order to add or refresh a token. -
-
-
    +
    -
    +
    +
      - Saturn Custody -

      - Saturn Custody -

      + Saturn Custody +

      + Saturn Custody +

      +
      +
    - -
    -
+ +
diff --git a/ui/pages/institutional/custody/custody.js b/ui/pages/institutional/custody/custody.js index 1257e1c57..3444ba010 100644 --- a/ui/pages/institutional/custody/custody.js +++ b/ui/pages/institutional/custody/custody.js @@ -259,8 +259,7 @@ const CustodyPage = () => { if (Object.keys(connectRequestValue).length) { setConnectRequest(connectRequestValue); setCurrentJwt( - connectRequestValue.token || - (await dispatch(mmiActions.getCustodianToken())), + connectRequestValue.token || dispatch(mmiActions.getCustodianToken()), ); setSelectedCustodianType(connectRequestValue.custodianType); setSelectedCustodianName(connectRequestValue.custodianName); @@ -345,7 +344,7 @@ const CustodyPage = () => { } return ( - <> + {connectError && ( {connectError} @@ -362,10 +361,8 @@ const CustodyPage = () => { padding={4} display={Display.Flex} flexDirection={FlexDirection.Column} - backgroundColor={Color.backgroundDefault} - style={{ - boxShadow: 'var(--shadow-size-xs) var(--color-shadow-default)', - }} + className="page-container__content" + width={BlockSize.Full} > { padding={4} display={Display.Flex} flexDirection={FlexDirection.Column} - backgroundColor={Color.backgroundDefault} - style={{ - boxShadow: 'var(--shadow-size-xs) var(--color-shadow-default)', - }} + className="page-container__content" + width={BlockSize.Full} > { /> {t('back')} - + {selectedCustodianImage && ( - {selectedCustodianImage && ( - {selectedCustodianDisplayName} - )} - {selectedCustodianDisplayName} + {selectedCustodianDisplayName} + + {selectedCustodianDisplayName} + - + )} {t('enterCustodianToken', [selectedCustodianDisplayName])} @@ -454,35 +449,37 @@ const CustodyPage = () => { ])} onUrlChange={(url) => setApiUrl(url)} /> - + + + + {loading ? ( + + ) : ( + - + )} )} @@ -625,6 +622,7 @@ const CustodyPage = () => { className="custody-accounts-empty__footer" > -
-
- -
+
+ +
+
diff --git a/ui/components/institutional/custody-labels/__snapshots__/custody-labels.test.js.snap b/ui/components/institutional/custody-labels/__snapshots__/custody-labels.test.js.snap index d79ae3d87..aea647170 100644 --- a/ui/components/institutional/custody-labels/__snapshots__/custody-labels.test.js.snap +++ b/ui/components/institutional/custody-labels/__snapshots__/custody-labels.test.js.snap @@ -7,7 +7,7 @@ exports[`CustodyLabels Component should render correctly 1`] = ` for="address-index" >

value

diff --git a/ui/components/institutional/custody-labels/custody-labels.js b/ui/components/institutional/custody-labels/custody-labels.js index 3f9d8700e..b095e5f3e 100644 --- a/ui/components/institutional/custody-labels/custody-labels.js +++ b/ui/components/institutional/custody-labels/custody-labels.js @@ -7,7 +7,7 @@ import { TextColor, FontWeight, BorderRadius, - TypographyVariant, + TextVariant, } from '../../../helpers/constants/design-system'; const CustodyLabels = (props) => { @@ -25,7 +25,7 @@ const CustodyLabels = (props) => { {filteredLabels.map((item) => ( { paddingLeft={2} paddingRight={2} backgroundColor={BackgroundColor.backgroundAlternative} - color={TextColor.textMuted} + color={TextColor.textDefault} fontWeight={FontWeight.Normal} borderRadius={BorderRadius.SM} - variant={TypographyVariant.H9} + variant={TextVariant.bodyXs} > {item.value} diff --git a/ui/components/institutional/custody-labels/index.scss b/ui/components/institutional/custody-labels/index.scss index 99695902a..8b93f0218 100644 --- a/ui/components/institutional/custody-labels/index.scss +++ b/ui/components/institutional/custody-labels/index.scss @@ -2,7 +2,7 @@ z-index: 1; letter-spacing: 0.5px; white-space: nowrap; - max-width: 80px; + max-width: 150px; text-overflow: ellipsis; overflow: hidden; display: block; diff --git a/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.js b/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.js index d5cb84547..232f4817f 100644 --- a/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.js +++ b/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.js @@ -1,19 +1,26 @@ import React, { useContext } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import Modal from '../../app/modal'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { MetaMetricsContext } from '../../../contexts/metametrics'; import { hideModal } from '../../../store/actions'; import { getSelectedAddress } from '../../../selectors/selectors'; import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; -import { Text } from '../../component-library'; -import Box from '../../ui/box'; import { - BLOCK_SIZES, + Box, + Button, + Modal, + ModalContent, + ModalHeader, + ModalOverlay, + Text, +} from '../../component-library'; + +import { + BlockSize, BackgroundColor, - DISPLAY, - FLEX_WRAP, - FLEX_DIRECTION, + Display, + FlexWrap, + FlexDirection, BorderRadius, FontWeight, TextAlign, @@ -42,77 +49,6 @@ const InteractiveReplacementTokenModal = () => { const custodian = custodians.find((item) => item.name === custodianName) || {}; - const renderCustodyInfo = () => { - let img; - - if (custodian.iconUrl) { - img = ( - - - {custodian.displayName} - - - ); - } else { - img = ( - - {custodian.displayName} - - ); - } - - return ( - <> - {img} - - {t('custodyRefreshTokenModalTitle')} - - - {t('custodyRefreshTokenModalDescription', [custodian.displayName])} - - - {t('custodyRefreshTokenModalSubtitle')} - - - {t('custodyRefreshTokenModalDescription1')} - - - {t('custodyRefreshTokenModalDescription2')} - - - ); - }; - const handleSubmit = () => { global.platform.openTab({ url, @@ -129,24 +65,68 @@ const InteractiveReplacementTokenModal = () => { }; return ( - - - {renderCustodyInfo(custodian)} - + + + + + {t('custodyRefreshTokenModalTitle')} + + {custodian.iconUrl ? ( + + + {custodian.displayName} + + + ) : ( + + {custodian.displayName} + + )} + + + {t('custodyRefreshTokenModalDescription', [custodian.displayName])} + + + {t('custodyRefreshTokenModalSubtitle')} + + + {t('custodyRefreshTokenModalDescription1')} + + + {t('custodyRefreshTokenModalDescription2')} + + + + ); }; diff --git a/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.test.js b/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.test.js index c6a1f8545..a1ea9359e 100644 --- a/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.test.js +++ b/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.test.js @@ -1,7 +1,5 @@ import React from 'react'; -import sinon from 'sinon'; import configureMockStore from 'redux-mock-store'; -import { fireEvent, waitFor } from '@testing-library/react'; import { renderWithProvider } from '../../../../test/lib/render-helpers'; import testData from '../../../../.storybook/test-data'; import InteractiveReplacementTokenModal from '.'; @@ -71,21 +69,4 @@ describe('Interactive Replacement Token Modal', function () { expect(getByTestId('interactive-replacement-token-modal')).toBeVisible(); expect(getByText('Your custodian session has expired')).toBeInTheDocument(); }); - - it('opens new tab on Open Codefi Compliance click', async () => { - global.platform = { openTab: sinon.spy() }; - - const { container } = renderWithProvider( - , - store, - ); - - const button = container.getElementsByClassName('btn-primary')[0]; - - fireEvent.click(button); - - await waitFor(() => { - expect(global.platform.openTab.calledOnce).toStrictEqual(true); - }); - }); }); diff --git a/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.js b/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.js index 5f1aa1c56..813a55662 100644 --- a/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.js +++ b/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.js @@ -6,13 +6,14 @@ import { getInteractiveReplacementToken } from '../../../selectors/institutional import { getIsUnlocked } from '../../../ducks/metamask/metamask'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { mmiActionsFactory } from '../../../store/institutional/institution-background'; +import { showInteractiveReplacementTokenModal } from '../../../store/institutional/institution-actions'; import { sha256 } from '../../../../shared/modules/hash.utils'; import { Size, IconColor, AlignItems, - DISPLAY, - BLOCK_SIZES, + Display, + BlockSize, JustifyContent, TextColor, TextVariant, @@ -24,10 +25,9 @@ import { IconSize, ButtonLink, Text, + Box, } from '../../component-library'; -import Box from '../../ui/box'; - const InteractiveReplacementTokenNotification = ({ isVisible }) => { const t = useI18nContext(); const dispatch = useDispatch(); @@ -48,10 +48,7 @@ const InteractiveReplacementTokenNotification = ({ isVisible }) => { interactiveReplacementToken && Boolean(Object.keys(interactiveReplacementToken).length); - if (!/^Custody/u.test(keyring.type)) { - setShowNotification(false); - return; - } else if (!hasInteractiveReplacementToken) { + if (!/^Custody/u.test(keyring.type) || !hasInteractiveReplacementToken) { setShowNotification(false); return; } @@ -98,34 +95,35 @@ const InteractiveReplacementTokenNotification = ({ isVisible }) => { return showNotification ? ( - + {t('custodySessionExpired')} - { - dispatch(mmiActions.showInteractiveReplacementTokenModal()); - }} - > - {t('learnMore')} - + + { + dispatch(showInteractiveReplacementTokenModal()); + }} + > + {t('learnMoreUpperCase')} + + ) : null; }; diff --git a/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.test.js b/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.test.js index 817600e2d..2d9a06f3d 100644 --- a/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.test.js +++ b/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.test.js @@ -10,10 +10,6 @@ import InteractiveReplacementTokenNotification from './interactive-replacement-t jest.mock('../../../../shared/modules/hash.utils'); -const mockedShowInteractiveReplacementTokenModal = jest - .fn() - .mockReturnValue({ type: 'TYPE' }); - const mockedGetCustodianToken = jest .fn() .mockReturnValue({ type: 'Custody', payload: 'token' }); @@ -32,11 +28,15 @@ jest.mock('../../../store/institutional/institution-background', () => ({ mmiActionsFactory: () => ({ getCustodianToken: mockedGetCustodianToken, getAllCustodianAccountsWithToken: mockedGetAllCustodianAccountsWithToken, - showInteractiveReplacementTokenModal: - mockedShowInteractiveReplacementTokenModal, }), })); +jest.mock('../../../store/institutional/institution-actions', () => ({ + showInteractiveReplacementTokenModal: jest + .fn() + .mockReturnValue({ type: 'TYPE' }), +})); + describe('Interactive Replacement Token Notification', () => { const selectedAddress = '0xca8f1F0245530118D0cf14a06b01Daf8f76Cf281'; @@ -112,8 +112,6 @@ describe('Interactive Replacement Token Notification', () => { await act(async () => { fireEvent.click(screen.getByTestId('show-modal')); }); - - expect(mockedShowInteractiveReplacementTokenModal).toHaveBeenCalled(); }); it('should render and call showNotification when component starts', async () => { diff --git a/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.js b/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.js index 07575238c..61a572f74 100644 --- a/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.js +++ b/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.js @@ -1,7 +1,7 @@ -import React, { useContext, useState } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; +import { isEqual } from 'lodash'; import { useHistory } from 'react-router-dom'; -import isEqual from 'lodash/isEqual'; import PulseLoader from '../../../components/ui/pulse-loader'; import { CUSTODY_ACCOUNT_ROUTE } from '../../../helpers/constants/routes'; import { @@ -47,8 +47,14 @@ const ConfirmAddCustodianToken = () => { const connectRequest = connectRequests ? connectRequests[0] : undefined; + useEffect(() => { + if (!connectRequest) { + history.push(mostRecentOverviewPage); + setIsLoading(false); + } + }, [connectRequest, history, mostRecentOverviewPage]); + if (!connectRequest) { - history.push(mostRecentOverviewPage); return null; } diff --git a/ui/pages/institutional/connect-custody/__snapshots__/account-list.test.js.snap b/ui/pages/institutional/connect-custody/__snapshots__/account-list.test.js.snap index ef1ca080f..1eb623034 100644 --- a/ui/pages/institutional/connect-custody/__snapshots__/account-list.test.js.snap +++ b/ui/pages/institutional/connect-custody/__snapshots__/account-list.test.js.snap @@ -3,186 +3,188 @@ exports[`CustodyAccountList renders accounts 1`] = `
`; diff --git a/ui/pages/institutional/connect-custody/account-list.js b/ui/pages/institutional/connect-custody/account-list.js index ca7de18b4..0cf1a85fe 100644 --- a/ui/pages/institutional/connect-custody/account-list.js +++ b/ui/pages/institutional/connect-custody/account-list.js @@ -1,6 +1,5 @@ import React from 'react'; import PropTypes from 'prop-types'; -import Button from '../../../components/ui/button'; import CustodyLabels from '../../../components/institutional/custody-labels'; import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../shared/constants/swaps'; import { CHAIN_IDS } from '../../../../shared/constants/network'; @@ -9,19 +8,24 @@ import Tooltip from '../../../components/ui/tooltip'; import { TextVariant, JustifyContent, - BLOCK_SIZES, - DISPLAY, + BlockSize, + Display, IconColor, + FlexDirection, + AlignItems, } from '../../../helpers/constants/design-system'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import Box from '../../../components/ui/box'; import { + Box, + Button, Text, Label, Icon, IconName, IconSize, ButtonLink, + BUTTON_VARIANT, + BUTTON_SIZES, } from '../../../components/component-library'; import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard'; @@ -34,7 +38,7 @@ export default function CustodyAccountList({ rawList, accounts, onAccountChange, - selectedAccounts = {}, + selectedAccounts, onCancel, onAddAccounts, custody, @@ -42,27 +46,28 @@ export default function CustodyAccountList({ const t = useI18nContext(); const [copied, handleCopy] = useCopyToClipboard(); const tooltipText = copied ? t('copiedExclamation') : t('copyToClipboard'); - const disabled = Object.keys(selectedAccounts).length === 0; + const disabled = + !selectedAccounts || Object.keys(selectedAccounts).length === 0; return ( - <> - + + {accounts.map((account, idx) => ( {!rawList && ( @@ -70,30 +75,27 @@ export default function CustodyAccountList({ type="checkbox" name="selectedAccount" id={`address-${idx}`} - value={account.address} - onChange={(e) => + onChange={() => onAccountChange({ name: account.name, - address: e.target.value, + address: account.address, custodianDetails: account.custodianDetails, labels: account.labels, chainId: account.chainId, }) } - checked={ - selectedAccounts && selectedAccounts[account.address] - } + checked={selectedAccounts[account.address] || false} /> )} {account.labels && ( @@ -172,38 +174,33 @@ export default function CustodyAccountList({ {!rawList && ( - - - + + + + + )} - + ); } diff --git a/ui/pages/institutional/custody/custody.js b/ui/pages/institutional/custody/custody.js index 3444ba010..56eda94e7 100644 --- a/ui/pages/institutional/custody/custody.js +++ b/ui/pages/institutional/custody/custody.js @@ -485,13 +485,9 @@ const CustodyPage = () => { )} {accounts && accounts.length > 0 && ( <> - + {t('selectAnAccount')} - + {t('selectAnAccountHelp')} @@ -518,22 +514,26 @@ const CustodyPage = () => { custody={selectedCustodianName} accounts={accounts} onAccountChange={(account) => { - if (selectedAccounts[account.address]) { - delete selectedAccounts[account.address]; - } else { - selectedAccounts[account.address] = { - name: account.name, - custodianDetails: account.custodianDetails, - labels: account.labels, - token: currentJwt, - apiUrl, - chainId: account.chainId, - custodyType: selectedCustodianType, - custodyName: selectedCustodianName, - }; - } + setSelectedAccounts((prevSelectedAccounts) => { + const updatedSelectedAccounts = { ...prevSelectedAccounts }; - setSelectedAccounts(selectedAccounts); + if (updatedSelectedAccounts[account.address]) { + delete updatedSelectedAccounts[account.address]; + } else { + updatedSelectedAccounts[account.address] = { + name: account.name, + custodianDetails: account.custodianDetails, + labels: account.labels, + token: currentJwt, + apiUrl, + chainId: account.chainId, + custodyType: selectedCustodianType, + custodyName: selectedCustodianName, + }; + } + + return updatedSelectedAccounts; + }); }} selectedAccounts={selectedAccounts} onAddAccounts={async () => { @@ -599,28 +599,25 @@ const CustodyPage = () => { )} {accounts && accounts.length === 0 && ( - - - {t('allCustodianAccountsConnectedTitle')} - - - {t('allCustodianAccountsConnectedSubtitle')} - - + <> + + {t('allCustodianAccountsConnectedTitle')} + + + {t('allCustodianAccountsConnectedSubtitle')} + + + - + )} ); diff --git a/ui/pages/institutional/custody/index.scss b/ui/pages/institutional/custody/index.scss deleted file mode 100644 index 0eeeb15af..000000000 --- a/ui/pages/institutional/custody/index.scss +++ /dev/null @@ -1,10 +0,0 @@ -.custody-accounts-empty { - min-height: 300px; - - &__footer { - border-top: 1px solid var(--color-border-muted); - position: absolute; - bottom: 0; - left: 0; - } -} diff --git a/ui/pages/institutional/institutional-entity-done-page/institutional-entity-done-page.js b/ui/pages/institutional/institutional-entity-done-page/institutional-entity-done-page.js index 164724acf..495b15d88 100644 --- a/ui/pages/institutional/institutional-entity-done-page/institutional-entity-done-page.js +++ b/ui/pages/institutional/institutional-entity-done-page/institutional-entity-done-page.js @@ -1,16 +1,22 @@ import React from 'react'; import PropTypes from 'prop-types'; import { useSelector } from 'react-redux'; -import Button from '../../../components/ui/button'; import { getMostRecentOverviewPage } from '../../../ducks/history/history'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import { Text } from '../../../components/component-library'; +import { + Text, + Box, + Button, + BUTTON_VARIANT, +} from '../../../components/component-library'; import { TextColor, - BorderRadius, TypographyVariant, + Display, + FlexDirection, + AlignItems, + TextAlign, } from '../../../helpers/constants/design-system'; -import Box from '../../../components/ui/box'; export default function InstitutionalEntityDonePage(props) { const mostRecentOverviewPage = useSelector(getMostRecentOverviewPage); @@ -19,7 +25,7 @@ export default function InstitutionalEntityDonePage(props) { const { state } = location; return ( - + - Entity image + {state.imgSrc && ( + Entity image + )} {state.description} - -
+ + -
+
); diff --git a/ui/pages/institutional/interactive-replacement-token-page/__snapshots__/interactive-replacement-token-page.test.js.snap b/ui/pages/institutional/interactive-replacement-token-page/__snapshots__/interactive-replacement-token-page.test.js.snap index 9d57ea9b9..000687750 100644 --- a/ui/pages/institutional/interactive-replacement-token-page/__snapshots__/interactive-replacement-token-page.test.js.snap +++ b/ui/pages/institutional/interactive-replacement-token-page/__snapshots__/interactive-replacement-token-page.test.js.snap @@ -3,57 +3,55 @@ exports[`Interactive Replacement Token Page should reject if there are errors 1`] = `
Replace custodian token
This is will replace the custodian token for the following address:
- + class="pulse-loader__loading-dot-one" + /> +
+
+
+
`; @@ -61,14 +59,14 @@ exports[`Interactive Replacement Token Page should reject if there are errors 1` exports[`Interactive Replacement Token Page should reject if there are errors 2`] = `
Replace custodian token @@ -76,10 +74,10 @@ exports[`Interactive Replacement Token Page should reject if there are errors 2`

Please go to displayName and click the 'Connect to MMI' button within their user interface to connect your accounts to MMI again.

-
- +
+
`; diff --git a/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.js b/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.js index 751168841..f3d83e988 100644 --- a/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.js +++ b/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.js @@ -4,7 +4,6 @@ import PropTypes from 'prop-types'; import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; import { getMostRecentOverviewPage } from '../../../ducks/history/history'; import { getMetaMaskAccounts } from '../../../selectors'; -import Button from '../../../components/ui/button'; import CustodyLabels from '../../../components/institutional/custody-labels/custody-labels'; import PulseLoader from '../../../components/ui/pulse-loader'; import { INSTITUTIONAL_FEATURES_DONE_ROUTE } from '../../../helpers/constants/routes'; @@ -17,7 +16,6 @@ import { mmiActionsFactory, showInteractiveReplacementTokenBanner, } from '../../../store/institutional/institution-background'; -import Box from '../../../components/ui/box'; import { Text, Label, @@ -25,14 +23,18 @@ import { ButtonLink, IconName, IconSize, + Box, + Button, + BUTTON_VARIANT, + BUTTON_SIZES, } from '../../../components/component-library'; import { - OVERFLOW_WRAP, + OverflowWrap, TextColor, JustifyContent, - BLOCK_SIZES, - DISPLAY, - FLEX_DIRECTION, + BlockSize, + Display, + FlexDirection, IconColor, } from '../../../helpers/constants/design-system'; import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard'; @@ -46,7 +48,9 @@ export default function InteractiveReplacementTokenPage({ history }) { const dispatch = useDispatch(); const isMountedRef = useRef(false); const mmiActions = mmiActionsFactory(); - const { address } = useSelector((state) => state.metamask.modal.props); + const address = useSelector( + (state) => state.appState.modal.modalState.props?.address, + ); const { selectedAddress, custodyAccountDetails, @@ -83,9 +87,12 @@ export default function InteractiveReplacementTokenPage({ history }) { }, []); useEffect(() => { + let isMounted = true; + const getTokenAccounts = async () => { if (!connectRequest) { history.push(mostRecentOverviewPage); + setIsLoading(false); return; } @@ -111,23 +118,37 @@ export default function InteractiveReplacementTokenPage({ history }) { metaMaskAccounts[account.address.toLowerCase()]?.balance || 0, })); - if (isMountedRef.current) { + if (isMounted) { setTokenAccounts(mappedAccounts); setIsLoading(false); } } catch (e) { setError(true); setIsLoading(false); + } finally { + if (isMounted) { + setIsLoading(false); + } } }; getTokenAccounts(); + + return () => { + isMounted = false; + }; // We just want to get the accounts in the render of the component // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + useEffect(() => { + if (!connectRequest) { + history.push(mostRecentOverviewPage); + setIsLoading(false); + } + }, [connectRequest, history, mostRecentOverviewPage]); + if (!connectRequest) { - history.push(mostRecentOverviewPage); return null; } @@ -142,8 +163,8 @@ export default function InteractiveReplacementTokenPage({ history }) { }; const handleReject = () => { + setIsLoading(true); onRemoveAddTokenConnectRequest(connectRequest); - history.push(mostRecentOverviewPage); }; const handleApprove = async () => { @@ -208,10 +229,10 @@ export default function InteractiveReplacementTokenPage({ history }) { @@ -221,123 +242,122 @@ export default function InteractiveReplacementTokenPage({ history }) { custodian.displayName || 'Custodian', ])} - ) : null} - - {tokenAccounts.map((account, idx) => { - return ( - + ) : ( + + {tokenAccounts.map((account, idx) => { + return ( - - - {account.labels && ( - - )} + + + + {account.labels && ( + + )} + - - ); - })} - + ); + })} + + )} - + {isLoading ? ( -
- -
+ ) : ( -
+ -
+
)}
diff --git a/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.test.js b/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.test.js index d462f4a7a..187acf4f9 100644 --- a/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.test.js +++ b/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.test.js @@ -166,8 +166,6 @@ describe('Interactive Replacement Token Page', function () { }); it('should call onRemoveAddTokenConnectRequest and navigate to mostRecentOverviewPage when handleReject is called', () => { - const mostRecentOverviewPage = '/mostRecentOverviewPage'; - const { getByText } = render(); fireEvent.click(getByText('Reject')); @@ -178,8 +176,6 @@ describe('Interactive Replacement Token Page', function () { apiUrl: connectRequests[0].apiUrl, token: connectRequests[0].token, }); - expect(props.history.push).toHaveBeenCalled(); - expect(props.history.push).toHaveBeenCalledWith(mostRecentOverviewPage); }); it('should call onRemoveAddTokenConnectRequest, setCustodianNewRefreshToken, and dispatch showInteractiveReplacementTokenBanner when handleApprove is called', async () => { diff --git a/ui/pages/pages.scss b/ui/pages/pages.scss index f9795cb28..313f1f538 100644 --- a/ui/pages/pages.scss +++ b/ui/pages/pages.scss @@ -15,7 +15,6 @@ @import 'connected-sites/index'; @import 'create-account/connect-hardware/index'; @import "institutional/connect-custody/index"; -@import "institutional/custody/index"; @import "institutional/institutional-entity-done-page/index"; @import "institutional/compliance-feature-page/index"; @import "institutional/confirm-add-custodian-token/index"; diff --git a/ui/store/institutional/institution-background.ts b/ui/store/institutional/institution-background.ts index 4b8f43d1c..626f43844 100644 --- a/ui/store/institutional/institution-background.ts +++ b/ui/store/institutional/institution-background.ts @@ -20,12 +20,14 @@ export function showInteractiveReplacementTokenBanner({ }: { url: string; oldRefreshToken: string; -}): ThunkAction { +}) { return async (dispatch: MetaMaskReduxDispatch) => { try { await submitRequestToBackground('showInteractiveReplacementTokenBanner', [ - url, - oldRefreshToken, + { + url, + oldRefreshToken, + }, ]); } catch (err: any) { if (err) { @@ -237,19 +239,21 @@ export function mmiActionsFactory() { custodyType, token, ]), - setCustodianNewRefreshToken: ( - address: string, - oldAuthDetails: string, - oldApiUrl: string, - newAuthDetails: string, - newApiUrl: string, - ) => + setCustodianNewRefreshToken: ({ + address, + oldAuthDetails, + oldApiUrl, + newAuthDetails, + newApiUrl, + }: { + address: string; + oldAuthDetails: string; + oldApiUrl: string; + newAuthDetails: string; + newApiUrl: string; + }) => createAsyncAction('setCustodianNewRefreshToken', [ - address, - oldAuthDetails, - oldApiUrl, - newAuthDetails, - newApiUrl, + { address, oldAuthDetails, oldApiUrl, newAuthDetails, newApiUrl }, ]), }; } From f145331665aacb17d32febe66487d5aedb9ee46f Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Thu, 13 Jul 2023 12:23:10 -0230 Subject: [PATCH 030/172] Fix memory based performance problem caused by use of lodash memoize in box component (#19993) --- ui/components/component-library/box/box.tsx | 2 +- ui/components/ui/box/box.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/components/component-library/box/box.tsx b/ui/components/component-library/box/box.tsx index 409b0b640..d09d0a6d6 100644 --- a/ui/components/component-library/box/box.tsx +++ b/ui/components/component-library/box/box.tsx @@ -130,7 +130,7 @@ const generateClassNames = memoize( } return classNamesObject; }, - (styleDeclaration, value) => [styleDeclaration, value], + (styleDeclaration, value) => `${styleDeclaration}${value}`, ); export const Box: BoxComponent = React.forwardRef( diff --git a/ui/components/ui/box/box.js b/ui/components/ui/box/box.js index 869413663..679dfb95c 100644 --- a/ui/components/ui/box/box.js +++ b/ui/components/ui/box/box.js @@ -184,7 +184,7 @@ const generateClassNames = memoize( } return classesObject; }, - (type, value) => [type, value], + (type, value) => `${type}${value}`, ); /** From 88c433cd09e2bd9ded15453538f7a5a023a86e98 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 12 Jul 2023 20:05:27 -0230 Subject: [PATCH 031/172] Prevent controller events from crashing (#19963) * Prevent controller events from crashing The package `@metamask/base-controller` has been updated to v3.1, which includes a change to how event subscriber errors are handled. Errors thrown in event subscribers will no longer interrupt event publishing. Subscriber errors are caught and thrown in a timeout handler, ensuring that they are logged and captured by Sentry. We can find any subscriber errors by looking at the background console, or at the Sentry dashboard. Fixes #19801 * Update LavaMoat policies --------- Co-authored-by: MetaMask Bot --- lavamoat/browserify/beta/policy.json | 3 +++ lavamoat/browserify/desktop/policy.json | 3 +++ lavamoat/browserify/flask/policy.json | 3 +++ lavamoat/browserify/main/policy.json | 3 +++ lavamoat/browserify/mmi/policy.json | 3 +++ package.json | 2 +- yarn.lock | 10 +++++----- 7 files changed, 21 insertions(+), 6 deletions(-) diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index f3373a420..4990fb1b9 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -855,6 +855,9 @@ } }, "@metamask/base-controller": { + "globals": { + "setTimeout": true + }, "packages": { "immer": true } diff --git a/lavamoat/browserify/desktop/policy.json b/lavamoat/browserify/desktop/policy.json index aa3b955d2..6cd8068ff 100644 --- a/lavamoat/browserify/desktop/policy.json +++ b/lavamoat/browserify/desktop/policy.json @@ -855,6 +855,9 @@ } }, "@metamask/base-controller": { + "globals": { + "setTimeout": true + }, "packages": { "immer": true } diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index aa3b955d2..6cd8068ff 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -855,6 +855,9 @@ } }, "@metamask/base-controller": { + "globals": { + "setTimeout": true + }, "packages": { "immer": true } diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index f3373a420..4990fb1b9 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -855,6 +855,9 @@ } }, "@metamask/base-controller": { + "globals": { + "setTimeout": true + }, "packages": { "immer": true } diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index a097c6d55..79411ecd1 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -1076,6 +1076,9 @@ } }, "@metamask/base-controller": { + "globals": { + "setTimeout": true + }, "packages": { "immer": true } diff --git a/package.json b/package.json index 8c04eefe8..fee7bf4ed 100644 --- a/package.json +++ b/package.json @@ -227,7 +227,7 @@ "@metamask/announcement-controller": "^4.0.0", "@metamask/approval-controller": "^3.3.0", "@metamask/assets-controllers": "^9.2.0", - "@metamask/base-controller": "^3.0.0", + "@metamask/base-controller": "^3.1.0", "@metamask/browser-passworder": "^4.1.0", "@metamask/contract-metadata": "^2.3.1", "@metamask/controller-utils": "^4.0.1", diff --git a/yarn.lock b/yarn.lock index a28073e73..c88669224 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3940,13 +3940,13 @@ __metadata: languageName: node linkType: hard -"@metamask/base-controller@npm:^3.0.0": - version: 3.0.0 - resolution: "@metamask/base-controller@npm:3.0.0" +"@metamask/base-controller@npm:^3.0.0, @metamask/base-controller@npm:^3.1.0": + version: 3.1.0 + resolution: "@metamask/base-controller@npm:3.1.0" dependencies: "@metamask/utils": ^5.0.2 immer: ^9.0.6 - checksum: a0853d90b024466c4108531cbf4459bd2f66fa6e0b912e42bd27cdf54262411a5601117649b6061424475ffa6b9714c5199d686c21e4d07c3b7b1ee0b4c17caa + checksum: fc1597a099e6d28bd089df936ca349d6c38c2e1b0f0737385cba30c34a5239241519eb172d77c70f8db2604f4dc5724f6893affe42bdd104cef98f9cfd6f1db8 languageName: node linkType: hard @@ -24504,7 +24504,7 @@ __metadata: "@metamask/approval-controller": ^3.3.0 "@metamask/assets-controllers": ^9.2.0 "@metamask/auto-changelog": ^2.1.0 - "@metamask/base-controller": ^3.0.0 + "@metamask/base-controller": ^3.1.0 "@metamask/browser-passworder": ^4.1.0 "@metamask/contract-metadata": ^2.3.1 "@metamask/controller-utils": ^4.0.1 From fac889c1116a2ab3c54b8243c6cf562f23d093f3 Mon Sep 17 00:00:00 2001 From: David Walsh Date: Wed, 12 Jul 2023 11:05:41 -0500 Subject: [PATCH 032/172] Fix #19548 - Increase address copy to clipboard time (#19948) --- .../multichain/address-copy-button/address-copy-button.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/components/multichain/address-copy-button/address-copy-button.js b/ui/components/multichain/address-copy-button/address-copy-button.js index 953bff31a..a46affac0 100644 --- a/ui/components/multichain/address-copy-button/address-copy-button.js +++ b/ui/components/multichain/address-copy-button/address-copy-button.js @@ -14,6 +14,7 @@ import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard'; import { shortenAddress } from '../../../helpers/utils/util'; import Tooltip from '../../ui/tooltip/tooltip'; import { useI18nContext } from '../../../hooks/useI18nContext'; +import { MINUTE } from '../../../../shared/constants/time'; export const AddressCopyButton = ({ address, @@ -22,7 +23,7 @@ export const AddressCopyButton = ({ onClick, }) => { const displayAddress = shorten ? shortenAddress(address) : address; - const [copied, handleCopy] = useCopyToClipboard(); + const [copied, handleCopy] = useCopyToClipboard(MINUTE); const t = useI18nContext(); return ( From 3c981d78d55107b68897a6effeec5bde228efbb2 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Thu, 13 Jul 2023 15:15:53 -0230 Subject: [PATCH 033/172] Update changelog for v10.34.0 (#20002) --- CHANGELOG.md | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 208946bb3..00d3852f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ## [10.34.0] +### Added +- Add a security quiz to the SRP reveal ([#19283](https://github.com/MetaMask/metamask-extension/pull/19283)) +- [FLASK] Add Snaps keyring and new snap accounts related pages ([#19710](https://github.com/MetaMask/metamask-extension/pull/19710)) + + +### Changed +- Decrease boldness of text in some labels ([#19731](https://github.com/MetaMask/metamask-extension/pull/19731)) + +### Fixed +- Fix design inconsistencies in the connect flow ([#19800](https://github.com/MetaMask/metamask-extension/pull/19800)) +- Fix connection issues on some dapps, and ensure that `eth_requestAccount` returns accounts when opening multiple tabs for the same dapp ([#19727](https://github.com/MetaMask/metamask-extension/pull/19727)) +- Fix UI bugs in contacts page ([#19646](https://github.com/MetaMask/metamask-extension/pull/19646)) +- Ensure correct logo shown on Linea ([#19717](https://github.com/MetaMask/metamask-extension/pull/19717)) +- Fix the autolock field in settings on firefox ([#19653](https://github.com/MetaMask/metamask-extension/pull/19653)) +- Prevent duplicate account names that only differ by letter casing ([#19616](https://github.com/MetaMask/metamask-extension/pull/19616)) +- Ensure token details stay within asset dropdown border ([#19626](https://github.com/MetaMask/metamask-extension/pull/19626)) +- Prevent rounded corners in account menu ([#19615](https://github.com/MetaMask/metamask-extension/pull/19615)) +- Ensure network changes before the user accepts a wallet_watchAsset request add the NFT to pre-change chain ID and address ([#19629](https://github.com/MetaMask/metamask-extension/pull/19629)) +- Fix performance degradations noticable on Firefox builds ([#19993](https://github.com/MetaMask/metamask-extension/pull/19993)) +- Fix copy to clipboard of public address, so that it is only cleared from the clipboard after 60 seconds ([#19948](https://github.com/MetaMask/metamask-extension/pull/19948)) +- Fix overlapping text, in some language, in home screen buttons ([#19920](https://github.com/MetaMask/metamask-extension/pull/19920)) + + ## [10.33.1] ### Fixed - Fix to bug causing users to see an infinite spinner when signing typed messages. ([#19894](https://github.com/MetaMask/metamask-extension/pull/19894)) @@ -3831,8 +3854,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added the ability to restore accounts from seed words. [Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.34.0...HEAD -[10.33.0]: https://github.com/MetaMask/metamask-extension/compare/v10.33.0...v10.34.0 -[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.33.1...HEAD +[10.34.0]: https://github.com/MetaMask/metamask-extension/compare/v10.33.1...v10.34.0 [10.33.1]: https://github.com/MetaMask/metamask-extension/compare/v10.33.0...v10.33.1 [10.33.0]: https://github.com/MetaMask/metamask-extension/compare/v10.32.0...v10.33.0 [10.32.0]: https://github.com/MetaMask/metamask-extension/compare/v10.31.1...v10.32.0 From 0ba409662e3ecd23421d9e810094a88c803bb249 Mon Sep 17 00:00:00 2001 From: David Walsh Date: Thu, 13 Jul 2023 12:52:27 -0500 Subject: [PATCH 034/172] UX: Remove Portfolio from Token Overview Page (#19988) Co-authored-by: Nidhi Kumari --- .../app/wallet-overview/token-overview.js | 36 +--------------- .../wallet-overview/token-overview.test.js | 42 ------------------- 2 files changed, 1 insertion(+), 77 deletions(-) diff --git a/ui/components/app/wallet-overview/token-overview.js b/ui/components/app/wallet-overview/token-overview.js index 0820c946a..a605492b9 100644 --- a/ui/components/app/wallet-overview/token-overview.js +++ b/ui/components/app/wallet-overview/token-overview.js @@ -28,7 +28,6 @@ import { INVALID_ASSET_TYPE } from '../../../helpers/constants/error-keys'; import { showModal } from '../../../store/actions'; import { MetaMetricsContext } from '../../../contexts/metametrics'; import { - MetaMetricsContextProp, MetaMetricsEventCategory, MetaMetricsEventName, MetaMetricsSwapsEventSource, @@ -36,12 +35,7 @@ import { import { AssetType } from '../../../../shared/constants/transaction'; import useRamps from '../../../hooks/experiences/useRamps'; -import { - ButtonIcon, - ButtonIconSize, - Icon, - IconName, -} from '../../component-library'; +import { Icon, IconName } from '../../component-library'; import { IconColor } from '../../../helpers/constants/design-system'; import { getPortfolioUrl } from '../../../helpers/utils/portfolio'; @@ -93,34 +87,6 @@ const TokenOverview = ({ className, token }) => { displayValue={balanceToRender} suffix={token.symbol} /> - { - const portfolioUrl = getPortfolioUrl('', 'ext', metaMetricsId); - global.platform.openTab({ - url: portfolioUrl, - }); - trackEvent( - { - category: MetaMetricsEventCategory.Home, - event: MetaMetricsEventName.PortfolioLinkClicked, - properties: { - url: portfolioUrl, - }, - }, - { - contextPropsIntoEventProperties: [ - MetaMetricsContextProp.PageTitle, - ], - }, - ); - }} - />
{formattedFiatBalance ? ( { ); }); - it('should always show the Portfolio button', () => { - const mockToken = { - name: 'test', - isERC721: false, - address: '0x7ceb23fd6bc0add59e62ac25578270cff1B9f619', - symbol: 'test', - }; - const { queryByTestId } = renderWithProvider( - , - store, - ); - const portfolioButton = queryByTestId('home__portfolio-site'); - expect(portfolioButton).toBeInTheDocument(); - }); - - it('should open the Portfolio URI when clicking on Portfolio button', async () => { - const mockToken = { - name: 'test', - isERC721: false, - address: '0x7ceb23fd6bc0add59e62ac25578270cff1B9f619', - symbol: 'test', - }; - const { queryByTestId } = renderWithProvider( - , - store, - ); - - const portfolioButton = queryByTestId('home__portfolio-site'); - - expect(portfolioButton).toBeInTheDocument(); - expect(portfolioButton).not.toBeDisabled(); - - fireEvent.click(portfolioButton); - expect(openTabSpy).toHaveBeenCalledTimes(1); - - await waitFor(() => - expect(openTabSpy).toHaveBeenCalledWith({ - url: expect.stringContaining(`?metamaskEntry=ext`), - }), - ); - }); - it('should show the Bridge button if chain id and token are supported', async () => { const mockToken = { name: 'test', From f17a841677c7b81a558fe238d6b79660a1c79c6d Mon Sep 17 00:00:00 2001 From: Nidhi Kumari Date: Thu, 13 Jul 2023 23:31:10 +0530 Subject: [PATCH 035/172] fixed button in wallet-overview (#19920) * fixed button in wallet-overview * lint fix * updated selector css with class --- ui/components/ui/icon-button/icon-button.js | 26 ++++++++++++++----- ui/components/ui/icon-button/icon-button.scss | 4 +++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/ui/components/ui/icon-button/icon-button.js b/ui/components/ui/icon-button/icon-button.js index c6eb9062a..cc95d8343 100644 --- a/ui/components/ui/icon-button/icon-button.js +++ b/ui/components/ui/icon-button/icon-button.js @@ -28,13 +28,25 @@ export default function IconButton({ {renderWrapper( <>
{Icon}
- - {label.length > 12 ? ( - {label} - ) : ( - label - )} - + {label.length > 9 ? ( + + + {label} + + + ) : ( + + {label} + + )} , )} diff --git a/ui/components/ui/icon-button/icon-button.scss b/ui/components/ui/icon-button/icon-button.scss index 14c0a9eaf..e80854307 100644 --- a/ui/components/ui/icon-button/icon-button.scss +++ b/ui/components/ui/icon-button/icon-button.scss @@ -29,4 +29,8 @@ opacity: 0.3; cursor: auto; } + + &__label { + width: 60px; //for ellipsis keeping the width same as icon-button used here + } } From 719d8a499b0cb557ec217a2c8fffd8b78315ef6c Mon Sep 17 00:00:00 2001 From: David Walsh Date: Thu, 13 Jul 2023 13:29:53 -0500 Subject: [PATCH 036/172] Fix #19941 - Correctly show network name and selection when chainIds collide (#19947) --- test/data/mock-state.json | 13 +++++- test/e2e/fixture-builder.js | 3 ++ test/e2e/tests/custom-rpc-history.spec.js | 10 +++-- .../__snapshots__/nft-details.test.js.snap | 2 +- .../app/nft-details/nft-details.test.js | 18 ++++++++- .../__snapshots__/app-header.test.js.snap | 4 +- .../network-list-menu/network-list-menu.js | 7 +++- ui/selectors/selectors.js | 13 +++++- ui/selectors/selectors.test.js | 40 +++++++++++++++++++ 9 files changed, 96 insertions(+), 14 deletions(-) diff --git a/test/data/mock-state.json b/test/data/mock-state.json index 07153cf85..77d17841f 100644 --- a/test/data/mock-state.json +++ b/test/data/mock-state.json @@ -115,13 +115,22 @@ "type": "rpc", "chainId": "0x5", "ticker": "ETH", - "id": "testNetworkConfigurationId" + "id": "chain5" }, "networkConfigurations": { "testNetworkConfigurationId": { "rpcUrl": "https://testrpc.com", "chainId": "0x1", - "nickname": "Custom Mainnet RPC" + "nickname": "Custom Mainnet RPC", + "type": "rpc", + "id": "testNetworkConfigurationId" + }, + "chain5": { + "type": "rpc", + "chainId": "0x5", + "ticker": "ETH", + "nickname": "Chain 5", + "id": "chain5" } }, "keyrings": [ diff --git a/test/e2e/fixture-builder.js b/test/e2e/fixture-builder.js index 884c9b94e..bbbcd49cf 100644 --- a/test/e2e/fixture-builder.js +++ b/test/e2e/fixture-builder.js @@ -215,6 +215,7 @@ function defaultFixture() { rpcUrl: 'http://localhost:8545', ticker: 'ETH', type: 'rpc', + id: 'networkConfigurationId', }, networkConfigurations: { networkConfigurationId: { @@ -346,6 +347,7 @@ function onboardingFixture() { rpcUrl: 'http://localhost:8545', chainId: CHAIN_IDS.LOCALHOST, nickname: 'Localhost 8545', + id: 'networkConfigurationId', }, networkConfigurations: { networkConfigurationId: { @@ -355,6 +357,7 @@ function onboardingFixture() { rpcUrl: 'http://localhost:8545', ticker: 'ETH', networkConfigurationId: 'networkConfigurationId', + type: 'rpc', }, }, }, diff --git a/test/e2e/tests/custom-rpc-history.spec.js b/test/e2e/tests/custom-rpc-history.spec.js index 8b43ab712..fd8e8314b 100644 --- a/test/e2e/tests/custom-rpc-history.spec.js +++ b/test/e2e/tests/custom-rpc-history.spec.js @@ -196,19 +196,21 @@ describe('Stores custom RPC history', function () { fixtures: new FixtureBuilder() .withNetworkController({ networkConfigurations: { - networkConfigurationId: { + networkConfigurationIdOne: { rpcUrl: 'http://127.0.0.1:8545/1', chainId: '0x539', ticker: 'ETH', nickname: 'http://127.0.0.1:8545/1', rpcPrefs: {}, + type: 'rpc', }, - networkConfigurationId2: { + networkConfigurationIdTwo: { rpcUrl: 'http://127.0.0.1:8545/2', chainId: '0x539', ticker: 'ETH', nickname: 'http://127.0.0.1:8545/2', rpcPrefs: {}, + type: 'rpc', }, }, }) @@ -248,14 +250,14 @@ describe('Stores custom RPC history', function () { fixtures: new FixtureBuilder() .withNetworkController({ networkConfigurations: { - networkConfigurationId: { + networkConfigurationIdOne: { rpcUrl: 'http://127.0.0.1:8545/1', chainId: '0x539', ticker: 'ETH', nickname: 'http://127.0.0.1:8545/1', rpcPrefs: {}, }, - networkConfigurationId2: { + networkConfigurationIdTwo: { rpcUrl: 'http://127.0.0.1:8545/2', chainId: '0x539', ticker: 'ETH', diff --git a/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap b/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap index 6be92d2bd..ec9fd7afe 100644 --- a/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap +++ b/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap @@ -66,7 +66,7 @@ exports[`NFT Details should match minimal props and state snapshot 1`] = ` class="box mm-text mm-avatar-base mm-avatar-base--size-sm mm-avatar-network nft-item__network-badge mm-text--body-sm mm-text--text-transform-uppercase box--display-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-text-default box--background-color-background-alternative box--rounded-full box--border-color-background-default box--border-width-2 box--border-style-solid" data-testid="nft-network-badge" > - G + C
diff --git a/ui/components/app/nft-details/nft-details.test.js b/ui/components/app/nft-details/nft-details.test.js index 3909406b2..aab54bd60 100644 --- a/ui/components/app/nft-details/nft-details.test.js +++ b/ui/components/app/nft-details/nft-details.test.js @@ -13,6 +13,12 @@ import { removeAndIgnoreNft, setRemoveNftMessage, } from '../../../store/actions'; +import { + CHAIN_IDS, + CURRENCY_SYMBOLS, + MAINNET_DISPLAY_NAME, + NETWORK_TYPES, +} from '../../../../shared/constants/network'; import NftDetails from './nft-details'; jest.mock('copy-to-clipboard'); @@ -172,7 +178,10 @@ describe('NFT Details', () => { metamask: { ...mockState.metamask, providerConfig: { - chainId: '0x1', + chainId: CHAIN_IDS.MAINNET, + type: NETWORK_TYPES.MAINNET, + ticker: CURRENCY_SYMBOLS.ETH, + nickname: MAINNET_DISPLAY_NAME, }, }, }; @@ -203,12 +212,16 @@ describe('NFT Details', () => { ...mockState.metamask, providerConfig: { chainId: '0x89', + type: 'rpc', + id: 'custom-mainnet', }, networkConfigurations: { testNetworkConfigurationId: { rpcUrl: 'https://testrpc.com', chainId: '0x89', nickname: 'Custom Mainnet RPC', + type: 'rpc', + id: 'custom-mainnet', }, }, }, @@ -239,7 +252,8 @@ describe('NFT Details', () => { metamask: { ...mockState.metamask, providerConfig: { - chainId: '0xaa36a7', + chainId: CHAIN_IDS.SEPOLIA, + type: NETWORK_TYPES.SEPOLIA, }, }, }; diff --git a/ui/components/multichain/app-header/__snapshots__/app-header.test.js.snap b/ui/components/multichain/app-header/__snapshots__/app-header.test.js.snap index 2a52b214f..a547951d2 100644 --- a/ui/components/multichain/app-header/__snapshots__/app-header.test.js.snap +++ b/ui/components/multichain/app-header/__snapshots__/app-header.test.js.snap @@ -214,12 +214,12 @@ exports[`App Header should match snapshot 1`] = `
- G + C

- Goerli + Chain 5

{ const showTestNetworks = useSelector(getShowTestNetworks); const currentChainId = useSelector(getCurrentChainId); + + const currentNetwork = useSelector(getCurrentNetwork); + const dispatch = useDispatch(); const history = useHistory(); const trackEvent = useContext(MetaMetricsContext); @@ -76,7 +80,8 @@ export const NetworkListMenu = ({ onClose }) => { if (!lineaMainnetReleased && network.providerType === 'linea-mainnet') { return null; } - const isCurrentNetwork = currentChainId === network.chainId; + const isCurrentNetwork = currentNetwork.id === network.id; + const canDeleteNetwork = !isCurrentNetwork && !UNREMOVABLE_CHAIN_IDS.includes(network.chainId); diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index b05b2c5e0..8707d26f9 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -1170,9 +1170,13 @@ export function getNetworkConfigurations(state) { export function getCurrentNetwork(state) { const allNetworks = getAllNetworks(state); - const currentChainId = getCurrentChainId(state); + const providerConfig = getProviderConfig(state); - return allNetworks.find((network) => network.chainId === currentChainId); + const filter = + providerConfig.type === 'rpc' + ? (network) => network.id === providerConfig.id + : (network) => network.id === providerConfig.type; + return allNetworks.find(filter); } export function getAllEnabledNetworks(state) { @@ -1193,6 +1197,7 @@ export function getTestNetworks(state) { rpcUrl: CHAIN_ID_TO_RPC_URL_MAP[CHAIN_IDS.GOERLI], providerType: NETWORK_TYPES.GOERLI, ticker: TEST_NETWORK_TICKER_MAP[NETWORK_TYPES.GOERLI], + id: NETWORK_TYPES.GOERLI, }, { chainId: CHAIN_IDS.SEPOLIA, @@ -1200,6 +1205,7 @@ export function getTestNetworks(state) { rpcUrl: CHAIN_ID_TO_RPC_URL_MAP[CHAIN_IDS.SEPOLIA], providerType: NETWORK_TYPES.SEPOLIA, ticker: TEST_NETWORK_TICKER_MAP[NETWORK_TYPES.SEPOLIA], + id: NETWORK_TYPES.SEPOLIA, }, { chainId: CHAIN_IDS.LINEA_GOERLI, @@ -1210,6 +1216,7 @@ export function getTestNetworks(state) { }, providerType: NETWORK_TYPES.LINEA_GOERLI, ticker: TEST_NETWORK_TICKER_MAP[NETWORK_TYPES.LINEA_GOERLI], + id: NETWORK_TYPES.LINEA_GOERLI, }, // Localhosts ...Object.values(networkConfigurations).filter( @@ -1232,6 +1239,7 @@ export function getNonTestNetworks(state) { }, providerType: NETWORK_TYPES.MAINNET, ticker: CURRENCY_SYMBOLS.ETH, + id: NETWORK_TYPES.MAINNET, }, { chainId: CHAIN_IDS.LINEA_MAINNET, @@ -1242,6 +1250,7 @@ export function getNonTestNetworks(state) { }, providerType: NETWORK_TYPES.LINEA_MAINNET, ticker: TEST_NETWORK_TICKER_MAP[NETWORK_TYPES.LINEA_MAINNET], + id: NETWORK_TYPES.LINEA_MAINNET, }, // Custom networks added by the user ...Object.values(networkConfigurations).filter( diff --git a/ui/selectors/selectors.test.js b/ui/selectors/selectors.test.js index 1442528f9..e63252ee7 100644 --- a/ui/selectors/selectors.test.js +++ b/ui/selectors/selectors.test.js @@ -316,6 +316,46 @@ describe('Selectors', () => { }); }); + describe('#getCurrentNetwork', () => { + it('returns the correct custom network when there is a chainId collision', () => { + const modifiedMockState = { + ...mockState, + metamask: { + ...mockState.metamask, + providerConfig: { + ...mockState.metamask.networkConfigurations + .testNetworkConfigurationId, + // 0x1 would collide with Ethereum Mainnet + chainId: '0x1', + // type of "rpc" signals custom network + type: 'rpc', + }, + }, + }; + + const currentNetwork = selectors.getCurrentNetwork(modifiedMockState); + expect(currentNetwork.nickname).toBe('Custom Mainnet RPC'); + expect(currentNetwork.chainId).toBe('0x1'); + }); + + it('returns the correct mainnet network when there is a chainId collision', () => { + const modifiedMockState = { + ...mockState, + metamask: { + ...mockState.metamask, + providerConfig: { + ...mockState.metamask.providerConfig, + chainId: '0x1', + // Changing type to 'mainnet' represents Ethereum Mainnet + type: 'mainnet', + }, + }, + }; + const currentNetwork = selectors.getCurrentNetwork(modifiedMockState); + expect(currentNetwork.nickname).toBe('Ethereum Mainnet'); + }); + }); + describe('#getAllEnabledNetworks', () => { it('returns only Mainnet and Linea with showTestNetworks off', () => { const networks = selectors.getAllEnabledNetworks({ From 090476d9a27ca712c90e813e91f94d00504e5015 Mon Sep 17 00:00:00 2001 From: Garrett Bear Date: Thu, 13 Jul 2023 13:22:40 -0700 Subject: [PATCH 037/172] ButtonIcon background & ButtonBase disabled update (#19976) * button background hover updates * add buttonlink underline * update button base disabled * fix size auto * Update ui/components/component-library/button-link/button-link.stories.js Co-authored-by: George Marshall * remove underline --------- Co-authored-by: George Marshall --- .../button-base/button-base.scss | 2 +- .../button-icon/button-icon.scss | 21 +++++++-- .../button-icon/button-icon.stories.tsx | 46 ++++++++++--------- .../button-icon/button-icon.test.tsx | 9 ++++ .../button-icon/button-icon.tsx | 5 +- .../button-icon/button-icon.types.ts | 1 + .../button-link/button-link.scss | 21 +++------ .../component-library-components.scss | 6 +++ 8 files changed, 67 insertions(+), 44 deletions(-) diff --git a/ui/components/component-library/button-base/button-base.scss b/ui/components/component-library/button-base/button-base.scss index 6b4e249c2..97115a116 100644 --- a/ui/components/component-library/button-base/button-base.scss +++ b/ui/components/component-library/button-base/button-base.scss @@ -33,7 +33,7 @@ &--disabled, &:disabled { - opacity: 0.3; + opacity: var(--opacity-disabled); cursor: not-allowed; } diff --git a/ui/components/component-library/button-icon/button-icon.scss b/ui/components/component-library/button-icon/button-icon.scss index 3658d6590..e42f1dd1e 100644 --- a/ui/components/component-library/button-icon/button-icon.scss +++ b/ui/components/component-library/button-icon/button-icon.scss @@ -1,7 +1,5 @@ .mm-button-icon { --button-icon-size: var(--size, 24px); - --button-icon-opacity-hover: 0.5; // TODO: replace with design tokens - --button-icon-opacity-disabled: 0.3; // TODO: replace with design tokens height: var(--button-icon-size); width: var(--button-icon-size); @@ -9,15 +7,24 @@ cursor: pointer; // ButtonIcon default states - &:active, + &:hover { - opacity: var(--button-icon-opacity-hover); + background-color: var(--color-background-hover); + } + + &:active { + background-color: var(--color-background-pressed); } &--disabled, &:disabled { - opacity: var(--button-icon-opacity-disabled); + opacity: var(--opacity-disabled); cursor: not-allowed; + + &:hover, + &:active { + background-color: transparent; + } } // ButtonIcon Sizes @@ -25,6 +32,10 @@ --button-icon-size: 24px; } + &--size-md { + --button-icon-size: 28px; + } + &--size-lg { --button-icon-size: 32px; } diff --git a/ui/components/component-library/button-icon/button-icon.stories.tsx b/ui/components/component-library/button-icon/button-icon.stories.tsx index d9afbca05..927faa8e7 100644 --- a/ui/components/component-library/button-icon/button-icon.stories.tsx +++ b/ui/components/component-library/button-icon/button-icon.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { ComponentStory, ComponentMeta } from '@storybook/react'; -import { Color } from '../../../helpers/constants/design-system'; +import { StoryFn, Meta } from '@storybook/react'; +import { IconColor } from '../../../helpers/constants/design-system'; import { IconName } from '..'; import { ButtonIconSize } from './button-icon.types'; import { ButtonIcon } from './button-icon'; @@ -21,11 +21,9 @@ export default { options: ['button', 'a'], }, }, -} as ComponentMeta; +} as Meta; -const Template: ComponentStory = (args) => ( - -); +const Template: StoryFn = (args) => ; export const DefaultStory = Template.bind({}); @@ -36,7 +34,7 @@ DefaultStory.args = { DefaultStory.storyName = 'Default'; -export const IconNameStory: ComponentStory = (args) => ( +export const IconNameStory: StoryFn = (args) => ( ); @@ -47,7 +45,7 @@ IconNameStory.args = { IconNameStory.storyName = 'IconName'; -export const SizeStory: ComponentStory = (args) => ( +export const SizeStory: StoryFn = (args) => ( <> = (args) => ( iconName={IconName.Close} ariaLabel="Close" /> + @@ -67,60 +71,60 @@ export const SizeStory: ComponentStory = (args) => ( SizeStory.storyName = 'Size'; -export const AriaLabel: ComponentStory = (args) => ( +export const AriaLabel: StoryFn = (args) => ( <> ); -export const As: ComponentStory = (args) => ( +export const As: StoryFn = (args) => ( <> ); -export const Href: ComponentStory = (args) => ( - +export const Href: StoryFn = (args) => ( + ); Href.args = { ariaLabel: 'Visit Metamask.io', href: 'https://metamask.io/', - color: Color.primaryDefault, + color: IconColor.primaryDefault, }; -export const ColorStory: ComponentStory = (args) => ( +export const ColorStory: StoryFn = (args) => ( ); ColorStory.storyName = 'Color'; ColorStory.args = { - color: Color.primaryDefault, + color: IconColor.primaryDefault, }; -export const Disabled: ComponentStory = (args) => ( +export const Disabled: StoryFn = (args) => ( ); diff --git a/ui/components/component-library/button-icon/button-icon.test.tsx b/ui/components/component-library/button-icon/button-icon.test.tsx index 1b4ae6a93..c146e1694 100644 --- a/ui/components/component-library/button-icon/button-icon.test.tsx +++ b/ui/components/component-library/button-icon/button-icon.test.tsx @@ -56,6 +56,12 @@ describe('ButtonIcon', () => { size={ButtonIconSize.Sm} data-testid={ButtonIconSize.Sm} /> + { expect(getByTestId(ButtonIconSize.Sm)).toHaveClass( `mm-button-icon--size-${ButtonIconSize.Sm}`, ); + expect(getByTestId(ButtonIconSize.Md)).toHaveClass( + `mm-button-icon--size-${ButtonIconSize.Md}`, + ); expect(getByTestId(ButtonIconSize.Lg)).toHaveClass( `mm-button-icon--size-${ButtonIconSize.Lg}`, ); diff --git a/ui/components/component-library/button-icon/button-icon.tsx b/ui/components/component-library/button-icon/button-icon.tsx index 3831cb838..36713dbe6 100644 --- a/ui/components/component-library/button-icon/button-icon.tsx +++ b/ui/components/component-library/button-icon/button-icon.tsx @@ -5,7 +5,7 @@ import { AlignItems, BackgroundColor, BorderRadius, - DISPLAY, + Display, IconColor, JustifyContent, } from '../../../helpers/constants/design-system'; @@ -17,6 +17,7 @@ import { ButtonIconSize, ButtonIconProps } from './button-icon.types'; const buttonIconSizeToIconSize: Record = { [ButtonIconSize.Sm]: IconSize.Sm, + [ButtonIconSize.Md]: IconSize.Md, [ButtonIconSize.Lg]: IconSize.Lg, }; @@ -52,7 +53,7 @@ export const ButtonIcon = React.forwardRef( )} color={color} {...(isDisabled ? { disabled: true } : {})} // only allow disabled attribute to be passed down to the Box when the as prop is equal to a button element - display={DISPLAY.INLINE_FLEX} + display={Display.InlineFlex} justifyContent={JustifyContent.center} alignItems={AlignItems.center} borderRadius={BorderRadius.LG} diff --git a/ui/components/component-library/button-icon/button-icon.types.ts b/ui/components/component-library/button-icon/button-icon.types.ts index d50d4cd85..70250075d 100644 --- a/ui/components/component-library/button-icon/button-icon.types.ts +++ b/ui/components/component-library/button-icon/button-icon.types.ts @@ -5,6 +5,7 @@ import { IconColor } from '../../../helpers/constants/design-system'; export enum ButtonIconSize { Sm = 'sm', + Md = 'md', Lg = 'lg', } diff --git a/ui/components/component-library/button-link/button-link.scss b/ui/components/component-library/button-link/button-link.scss index 30e40042c..9d68e42d8 100644 --- a/ui/components/component-library/button-link/button-link.scss +++ b/ui/components/component-library/button-link/button-link.scss @@ -1,36 +1,27 @@ -.mm-button-link { - &:hover { - opacity: 0.5; - } +.mm-button-link { &:active { - opacity: 0.5; + color: var(--color-primary-alternative); } &--disabled { - &:hover { - opacity: 0.3; - } - &:active { - opacity: 0.3; + color: var(--color-primary-default); } } &--type-danger { &:hover { color: var(--color-error-default); - opacity: 0.5; } &:active { - color: var(--color-error-default); - opacity: 0.5; + color: var(--color-error-alternative); } } - &--type-danger#{&}--disabled:hover { - opacity: 0.3; + &--type-danger#{&}--disabled:active { + color: var(--color-error-default); } &--size-auto { diff --git a/ui/components/component-library/component-library-components.scss b/ui/components/component-library/component-library-components.scss index 68f1085c9..d03fb28f1 100644 --- a/ui/components/component-library/component-library-components.scss +++ b/ui/components/component-library/component-library-components.scss @@ -4,6 +4,12 @@ * This will help improve specificity and reduce the chance of * unintended overrides. **/ + +// Temp CSS Variables +:root { + --opacity-disabled: 0.5; +} + // Atoms @import 'box/box'; @import 'text/text'; From 0917b7c52f993373053b36e10ab6a13e8f50e527 Mon Sep 17 00:00:00 2001 From: Ariella Vu <20778143+digiwand@users.noreply.github.com> Date: Thu, 13 Jul 2023 22:38:42 +0200 Subject: [PATCH 038/172] Add alternative summary UI with arrow icon to the Disclosure component (#19770) * disclosure: add isArrowSummary option w/ UI * disclosure.scss: add missing trailing semicolon * Disclosure: replace isArrowSummary -> type prop * Disclosure: alphabetize props * Disclosure: add cursor: pointer * storybook: add Disclosure - Type Arrow * Disclosure: margin-left: 0 arrow type content * Disclosure: fix margin-left: 0 arrow type * Disclosure: support Text media query for Arrow * Disclosure: clean rn type -> variant * Disclosure: use size prop for arrow summary text * Disclosure: update rest of type -> variant * Disclosure: 1 more type -> variant * Disclosure: TypeArrow -> VariantArrow --- .../ui/disclosure/disclosure.constants.ts | 4 ++ ui/components/ui/disclosure/disclosure.js | 63 +++++++++++++++---- ui/components/ui/disclosure/disclosure.scss | 28 +++++++++ .../ui/disclosure/disclosure.stories.js | 20 ++++-- 4 files changed, 98 insertions(+), 17 deletions(-) create mode 100644 ui/components/ui/disclosure/disclosure.constants.ts diff --git a/ui/components/ui/disclosure/disclosure.constants.ts b/ui/components/ui/disclosure/disclosure.constants.ts new file mode 100644 index 000000000..4326545de --- /dev/null +++ b/ui/components/ui/disclosure/disclosure.constants.ts @@ -0,0 +1,4 @@ +export enum DisclosureVariant { + Default = 'default', + Arrow = 'arrow', +} diff --git a/ui/components/ui/disclosure/disclosure.js b/ui/components/ui/disclosure/disclosure.js index e20746308..297646c09 100644 --- a/ui/components/ui/disclosure/disclosure.js +++ b/ui/components/ui/disclosure/disclosure.js @@ -1,9 +1,53 @@ import React, { useState, useRef, useEffect } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -import { Icon, IconName, IconSize } from '../../component-library'; +import { Icon, IconName, IconSize, Text } from '../../component-library'; +import { Color, TextVariant } from '../../../helpers/constants/design-system'; +import { DisclosureVariant } from './disclosure.constants'; -const Disclosure = ({ children, title, size }) => { +/** + * @param {string} variant + * @param {string} title + * @param {string} size + * @returns {JSX.Element} + */ +const renderSummaryByType = (variant, title, size) => { + switch (variant) { + case DisclosureVariant.Arrow: { + const textVariant = + size === 'small' ? TextVariant.bodySm : TextVariant.bodyMd; + + return ( + + + {title} + + + + ); + } + default: + return ( + + + {title} + + ); + } +}; + +const Disclosure = ({ children, title, size, variant }) => { const disclosureFooterEl = useRef(null); const [open, setOpen] = useState(false); @@ -23,15 +67,8 @@ const Disclosure = ({ children, title, size }) => {
setOpen((state) => !state)}> {title ? (
- - - {title} - + {renderSummaryByType(variant, title)} +
{children}
@@ -46,13 +83,15 @@ const Disclosure = ({ children, title, size }) => { Disclosure.propTypes = { children: PropTypes.node.isRequired, - title: PropTypes.string, size: PropTypes.string, + title: PropTypes.string, + variant: PropTypes.string, }; Disclosure.defaultProps = { size: 'normal', title: null, + variant: DisclosureVariant.Default, }; export default Disclosure; diff --git a/ui/components/ui/disclosure/disclosure.scss b/ui/components/ui/disclosure/disclosure.scss index 06b9044b1..179de33db 100644 --- a/ui/components/ui/disclosure/disclosure.scss +++ b/ui/components/ui/disclosure/disclosure.scss @@ -7,6 +7,7 @@ padding-bottom: 10px; font-weight: bold; display: flex; + cursor: pointer; &::-webkit-details-marker, &::marker { @@ -23,4 +24,31 @@ font-size: 12px; } } + + // Arrow Summary + + details[open] { + .disclosure__summary.is-arrow .disclosure__summary--icon { + transform: rotateX(0deg); + } + } + + &__summary.is-arrow { + display: flex; + align-items: center; + font-weight: normal; + + &:hover { + opacity: 0.5; + } + + + .disclosure__content { + margin-left: 0; + } + + .disclosure__summary--icon { + transform: rotateX(180deg); + transition: 0.1s transform; + } + } } diff --git a/ui/components/ui/disclosure/disclosure.stories.js b/ui/components/ui/disclosure/disclosure.stories.js index 708ab5ed4..6b091528d 100644 --- a/ui/components/ui/disclosure/disclosure.stories.js +++ b/ui/components/ui/disclosure/disclosure.stories.js @@ -1,4 +1,5 @@ import React from 'react'; +import { DisclosureVariant } from './disclosure.constants'; import Disclosure from '.'; export default { @@ -8,20 +9,29 @@ export default { children: { control: 'text', }, - title: { - control: 'text', - }, size: { control: 'text', }, + title: { + control: 'text', + }, + variant: { + control: { + type: 'select', + }, + options: [...Object.values(DisclosureVariant)], + }, }, args: { - title: 'title', children: 'hello world', size: 'normal', + title: 'title', }, }; export const DefaultStory = (args) => ; - DefaultStory.storyName = 'Default'; + +export const VariantArrow = (args) => ( + +); From 3ef2faf41c46fa7b1bb61b3f31cbb92406abdf67 Mon Sep 17 00:00:00 2001 From: Howard Braham Date: Thu, 13 Jul 2023 13:49:13 -0700 Subject: [PATCH 039/172] fix(clipboard): Increase DEFAULT copy to clipboard time (#20008) --- ui/hooks/useCopyToClipboard.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/hooks/useCopyToClipboard.js b/ui/hooks/useCopyToClipboard.js index 8f6384ac0..2aead9976 100644 --- a/ui/hooks/useCopyToClipboard.js +++ b/ui/hooks/useCopyToClipboard.js @@ -1,6 +1,6 @@ import { useState, useCallback } from 'react'; import copyToClipboard from 'copy-to-clipboard'; -import { SECOND } from '../../shared/constants/time'; +import { MINUTE } from '../../shared/constants/time'; import { useTimeout } from './useTimeout'; /** @@ -9,7 +9,7 @@ import { useTimeout } from './useTimeout'; * @param {number} [delay=3000] - delay in ms * @returns {[boolean, Function]} */ -const DEFAULT_DELAY = SECOND * 3; +const DEFAULT_DELAY = MINUTE; export function useCopyToClipboard(delay = DEFAULT_DELAY) { const [copied, setCopied] = useState(false); From 751120bd014b2dce478a97f8547b5567eefdc38d Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Thu, 13 Jul 2023 16:57:31 -0600 Subject: [PATCH 040/172] Restore support for Linea networks (#20011) When the NetworkController in this repo was replaced with `@metamask/network-controller`, support for Linea networks was lost as it did not support it at that time. `@metamask/network-controller` has since been updated, so this commit bumps that package to restore support. --- .iyarc | 4 ++ lavamoat/browserify/beta/policy.json | 22 +------- lavamoat/browserify/desktop/policy.json | 22 +------- lavamoat/browserify/flask/policy.json | 22 +------- lavamoat/browserify/main/policy.json | 22 +------- lavamoat/browserify/mmi/policy.json | 22 +------- package.json | 4 +- yarn.lock | 71 +++++++++++-------------- 8 files changed, 43 insertions(+), 146 deletions(-) diff --git a/.iyarc b/.iyarc index 9e16de044..2b0adcf36 100644 --- a/.iyarc +++ b/.iyarc @@ -9,3 +9,7 @@ GHSA-p8p7-x288-28g6 # Not easily patched # Minimal risk to us because we're using lockdown which also prevents this case of prototype pollution GHSA-h755-8qp9-cq85 + +# tough-cookie +# this will go away soon when we get rid of web3-provider-engine +GHSA-72xf-g2v4-qvf3 diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index d0c93d301..a23f68f9b 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -1624,7 +1624,7 @@ }, "packages": { "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": true, + "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, "eth-rpc-errors": true, "json-rpc-engine": true, "node-fetch": true @@ -1642,26 +1642,6 @@ "superstruct": true } }, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": { - "globals": { - "URL": true, - "btoa": true, - "console.error": true, - "fetch": true, - "setTimeout": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/eth-sig-util": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>pify": true, - "@metamask/safe-event-emitter": true, - "browserify>browser-resolve": true, - "eth-rpc-errors": true, - "json-rpc-engine": true, - "lavamoat>json-stable-stringify": true, - "vinyl>clone": true - } - }, "@metamask/network-controller>@metamask/eth-json-rpc-provider": { "packages": { "@metamask/safe-event-emitter": true, diff --git a/lavamoat/browserify/desktop/policy.json b/lavamoat/browserify/desktop/policy.json index e9133848b..4c80538b4 100644 --- a/lavamoat/browserify/desktop/policy.json +++ b/lavamoat/browserify/desktop/policy.json @@ -1750,7 +1750,7 @@ }, "packages": { "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": true, + "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, "eth-rpc-errors": true, "json-rpc-engine": true, "node-fetch": true @@ -1768,26 +1768,6 @@ "superstruct": true } }, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": { - "globals": { - "URL": true, - "btoa": true, - "console.error": true, - "fetch": true, - "setTimeout": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/eth-sig-util": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>pify": true, - "@metamask/safe-event-emitter": true, - "browserify>browser-resolve": true, - "eth-rpc-errors": true, - "json-rpc-engine": true, - "lavamoat>json-stable-stringify": true, - "vinyl>clone": true - } - }, "@metamask/network-controller>@metamask/eth-json-rpc-provider": { "packages": { "@metamask/safe-event-emitter": true, diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index e9133848b..4c80538b4 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -1750,7 +1750,7 @@ }, "packages": { "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": true, + "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, "eth-rpc-errors": true, "json-rpc-engine": true, "node-fetch": true @@ -1768,26 +1768,6 @@ "superstruct": true } }, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": { - "globals": { - "URL": true, - "btoa": true, - "console.error": true, - "fetch": true, - "setTimeout": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/eth-sig-util": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>pify": true, - "@metamask/safe-event-emitter": true, - "browserify>browser-resolve": true, - "eth-rpc-errors": true, - "json-rpc-engine": true, - "lavamoat>json-stable-stringify": true, - "vinyl>clone": true - } - }, "@metamask/network-controller>@metamask/eth-json-rpc-provider": { "packages": { "@metamask/safe-event-emitter": true, diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index d0c93d301..a23f68f9b 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -1624,7 +1624,7 @@ }, "packages": { "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": true, + "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, "eth-rpc-errors": true, "json-rpc-engine": true, "node-fetch": true @@ -1642,26 +1642,6 @@ "superstruct": true } }, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": { - "globals": { - "URL": true, - "btoa": true, - "console.error": true, - "fetch": true, - "setTimeout": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/eth-sig-util": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>pify": true, - "@metamask/safe-event-emitter": true, - "browserify>browser-resolve": true, - "eth-rpc-errors": true, - "json-rpc-engine": true, - "lavamoat>json-stable-stringify": true, - "vinyl>clone": true - } - }, "@metamask/network-controller>@metamask/eth-json-rpc-provider": { "packages": { "@metamask/safe-event-emitter": true, diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index c2c8c36c1..d198cb950 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -1852,7 +1852,7 @@ }, "packages": { "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": true, + "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, "eth-rpc-errors": true, "json-rpc-engine": true, "node-fetch": true @@ -1870,26 +1870,6 @@ "superstruct": true } }, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": { - "globals": { - "URL": true, - "btoa": true, - "console.error": true, - "fetch": true, - "setTimeout": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/eth-sig-util": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>pify": true, - "@metamask/safe-event-emitter": true, - "browserify>browser-resolve": true, - "eth-rpc-errors": true, - "json-rpc-engine": true, - "lavamoat>json-stable-stringify": true, - "vinyl>clone": true - } - }, "@metamask/network-controller>@metamask/eth-json-rpc-provider": { "packages": { "@metamask/safe-event-emitter": true, diff --git a/package.json b/package.json index 9a6ee69c5..942832714 100644 --- a/package.json +++ b/package.json @@ -232,7 +232,7 @@ "@metamask/base-controller": "^3.1.0", "@metamask/browser-passworder": "^4.1.0", "@metamask/contract-metadata": "^2.3.1", - "@metamask/controller-utils": "^4.1.0", + "@metamask/controller-utils": "^4.2.0", "@metamask/design-tokens": "^1.12.0", "@metamask/desktop": "^0.3.0", "@metamask/eth-json-rpc-middleware": "^11.0.0", @@ -248,7 +248,7 @@ "@metamask/logo": "^3.1.1", "@metamask/message-manager": "^7.0.2", "@metamask/metamask-eth-abis": "^3.0.0", - "@metamask/network-controller": "^10.3.0", + "@metamask/network-controller": "^10.3.1", "@metamask/notification-controller": "^3.0.0", "@metamask/obs-store": "^8.1.0", "@metamask/permission-controller": "^4.0.0", diff --git a/yarn.lock b/yarn.lock index 60ddf503a..b4ca89b19 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4027,9 +4027,9 @@ __metadata: languageName: node linkType: hard -"@metamask/controller-utils@npm:^4.0.0, @metamask/controller-utils@npm:^4.0.1, @metamask/controller-utils@npm:^4.1.0": - version: 4.1.0 - resolution: "@metamask/controller-utils@npm:4.1.0" +"@metamask/controller-utils@npm:^4.0.0, @metamask/controller-utils@npm:^4.0.1, @metamask/controller-utils@npm:^4.1.0, @metamask/controller-utils@npm:^4.2.0": + version: 4.2.0 + resolution: "@metamask/controller-utils@npm:4.2.0" dependencies: "@metamask/utils": ^5.0.2 "@spruceid/siwe-parser": 1.1.3 @@ -4040,7 +4040,7 @@ __metadata: ethereumjs-util: ^7.0.10 ethjs-unit: ^0.1.6 fast-deep-equal: ^3.1.3 - checksum: b4975e6ca860b691931254aa749e8c4faddd04279609cf197155b38150e55da0e966bf9b2d61ee1cd070f79d16e0305d5a0ff1747e0b4ab2e1c3ab46ca84e4d7 + checksum: e71779577c37038e6e605a43ef6b9c1af82e0b3887a72c01f48ae1e4e2005116fc9d09c8b690139478c04dd2929e227642c5fd80cfbc81814d667c415c714228 languageName: node linkType: hard @@ -4141,16 +4141,16 @@ __metadata: languageName: node linkType: hard -"@metamask/eth-json-rpc-infura@npm:^8.0.0": - version: 8.1.0 - resolution: "@metamask/eth-json-rpc-infura@npm:8.1.0" +"@metamask/eth-json-rpc-infura@npm:^8.1.0": + version: 8.1.1 + resolution: "@metamask/eth-json-rpc-infura@npm:8.1.1" dependencies: - "@metamask/utils": ^3.0.1 - eth-json-rpc-middleware: ^9.0.0 + "@metamask/eth-json-rpc-provider": ^1.0.0 + "@metamask/utils": ^4.0.0 eth-rpc-errors: ^4.0.3 json-rpc-engine: ^6.1.0 node-fetch: ^2.6.7 - checksum: fd09383e2b3c16187b8889b53bfc431fc7ea4f6483acc23ddf77f2fd771ad0fbff41d6a62d4b05833e7cda66adafe0cb3730d7c0e9575b89683b71a82ab1ee1f + checksum: ab4ce53fcc1586344824d58aed4d71412b015466f697758b4849e186038ae1730c9765935dfaf1a9131ff1a8f0f36dcb66fd50355ed95ac7a4bf0bc18c4c2696 languageName: node linkType: hard @@ -4398,13 +4398,13 @@ __metadata: languageName: node linkType: hard -"@metamask/network-controller@npm:^10.2.0, @metamask/network-controller@npm:^10.3.0": - version: 10.3.0 - resolution: "@metamask/network-controller@npm:10.3.0" +"@metamask/network-controller@npm:^10.2.0, @metamask/network-controller@npm:^10.3.0, @metamask/network-controller@npm:^10.3.1": + version: 10.3.1 + resolution: "@metamask/network-controller@npm:10.3.1" dependencies: - "@metamask/base-controller": ^3.0.0 - "@metamask/controller-utils": ^4.1.0 - "@metamask/eth-json-rpc-infura": ^8.0.0 + "@metamask/base-controller": ^3.1.0 + "@metamask/controller-utils": ^4.2.0 + "@metamask/eth-json-rpc-infura": ^8.1.0 "@metamask/eth-json-rpc-middleware": ^11.0.0 "@metamask/eth-json-rpc-provider": ^1.0.0 "@metamask/swappable-obj-proxy": ^2.1.0 @@ -4417,7 +4417,7 @@ __metadata: immer: ^9.0.6 json-rpc-engine: ^6.1.0 uuid: ^8.3.2 - checksum: 0c48625af9c18be3ed2a433209db770bab02e667e251be1ef4c1f61a62c25907536ff740712bdfd799ac923a4a6bb9df5430ead8d4215507bbf30dcc7a40d53c + checksum: 62adb90b02eae1236f9c1c3ceb70c9de0f4e390c3b68ced0c81b0b867dced7814d5d805cdfb6e0ccc9e62b82fac762f70c204f08feb3f3ee5647610d079cbdd7 languageName: node linkType: hard @@ -5107,7 +5107,7 @@ __metadata: languageName: node linkType: hard -"@metamask/utils@npm:^3.0.1, @metamask/utils@npm:^3.0.3, @metamask/utils@npm:^3.4.1": +"@metamask/utils@npm:^3.0.3, @metamask/utils@npm:^3.4.1": version: 3.6.0 resolution: "@metamask/utils@npm:3.6.0" dependencies: @@ -5119,6 +5119,18 @@ __metadata: languageName: node linkType: hard +"@metamask/utils@npm:^4.0.0": + version: 4.0.0 + resolution: "@metamask/utils@npm:4.0.0" + dependencies: + "@types/debug": ^4.1.7 + debug: ^4.3.4 + semver: ^7.3.8 + superstruct: ^1.0.3 + checksum: 6d4edca78fe1f66504ed5e5ca021a67f4b4e0893e86484c746b87039c2161c39d3b8bd8e4b9235ddfd023b2d76dd54210af94ec5550e27bc4ad9c0d7d5f3f231 + languageName: node + linkType: hard + "@metamask/utils@npm:^5.0.0, @metamask/utils@npm:^5.0.1, @metamask/utils@npm:^5.0.2": version: 5.0.2 resolution: "@metamask/utils@npm:5.0.2" @@ -16119,25 +16131,6 @@ __metadata: languageName: node linkType: hard -"eth-json-rpc-middleware@npm:^9.0.0": - version: 9.0.1 - resolution: "eth-json-rpc-middleware@npm:9.0.1" - dependencies: - "@metamask/eth-sig-util": ^5.0.0 - "@metamask/safe-event-emitter": ^2.0.0 - "@metamask/utils": ^3.0.3 - btoa: ^1.2.1 - clone: ^2.1.1 - eth-block-tracker: ^5.0.1 - eth-rpc-errors: ^4.0.3 - json-rpc-engine: ^6.1.0 - json-stable-stringify: ^1.0.1 - node-fetch: ^2.6.7 - pify: ^3.0.0 - checksum: 9512829a6958df6ef739b891a0c0804b51a140407fd2e3ddaaa6b18d975796646cfcf7f7305a18beb7903db09e0c7a91b06dc5434b6bd2d6cdb85d992d9fd3ab - languageName: node - linkType: hard - "eth-lattice-keyring@npm:^0.12.4": version: 0.12.4 resolution: "eth-lattice-keyring@npm:0.12.4" @@ -24659,7 +24652,7 @@ __metadata: "@metamask/base-controller": ^3.1.0 "@metamask/browser-passworder": ^4.1.0 "@metamask/contract-metadata": ^2.3.1 - "@metamask/controller-utils": ^4.1.0 + "@metamask/controller-utils": ^4.2.0 "@metamask/design-tokens": ^1.12.0 "@metamask/desktop": ^0.3.0 "@metamask/eslint-config": ^9.0.0 @@ -24681,7 +24674,7 @@ __metadata: "@metamask/logo": ^3.1.1 "@metamask/message-manager": ^7.0.2 "@metamask/metamask-eth-abis": ^3.0.0 - "@metamask/network-controller": ^10.3.0 + "@metamask/network-controller": ^10.3.1 "@metamask/notification-controller": ^3.0.0 "@metamask/obs-store": ^8.1.0 "@metamask/permission-controller": ^4.0.0 From 710101991c1495a9036070650a6bf4301d4a108c Mon Sep 17 00:00:00 2001 From: Nidhi Kumari Date: Thu, 13 Jul 2023 23:31:10 +0530 Subject: [PATCH 041/172] fixed button in wallet-overview (#19920) * fixed button in wallet-overview * lint fix * updated selector css with class --- ui/components/ui/icon-button/icon-button.js | 26 ++++++++++++++----- ui/components/ui/icon-button/icon-button.scss | 4 +++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/ui/components/ui/icon-button/icon-button.js b/ui/components/ui/icon-button/icon-button.js index c6eb9062a..cc95d8343 100644 --- a/ui/components/ui/icon-button/icon-button.js +++ b/ui/components/ui/icon-button/icon-button.js @@ -28,13 +28,25 @@ export default function IconButton({ {renderWrapper( <>
{Icon}
- - {label.length > 12 ? ( - {label} - ) : ( - label - )} - + {label.length > 9 ? ( + + + {label} + + + ) : ( + + {label} + + )} , )} diff --git a/ui/components/ui/icon-button/icon-button.scss b/ui/components/ui/icon-button/icon-button.scss index 14c0a9eaf..e80854307 100644 --- a/ui/components/ui/icon-button/icon-button.scss +++ b/ui/components/ui/icon-button/icon-button.scss @@ -29,4 +29,8 @@ opacity: 0.3; cursor: auto; } + + &__label { + width: 60px; //for ellipsis keeping the width same as icon-button used here + } } From 6c04d765022e55341148132228301b35688ac30b Mon Sep 17 00:00:00 2001 From: David Walsh Date: Thu, 13 Jul 2023 13:29:53 -0500 Subject: [PATCH 042/172] Fix #19941 - Correctly show network name and selection when chainIds collide (#19947) --- test/data/mock-state.json | 13 +++++- test/e2e/fixture-builder.js | 3 ++ test/e2e/tests/custom-rpc-history.spec.js | 10 +++-- .../__snapshots__/nft-details.test.js.snap | 2 +- .../app/nft-details/nft-details.test.js | 18 ++++++++- .../__snapshots__/app-header.test.js.snap | 4 +- .../network-list-menu/network-list-menu.js | 6 ++- ui/selectors/selectors.js | 13 +++++- ui/selectors/selectors.test.js | 40 +++++++++++++++++++ ui/store/actions.ts | 3 -- 10 files changed, 95 insertions(+), 17 deletions(-) diff --git a/test/data/mock-state.json b/test/data/mock-state.json index 07153cf85..77d17841f 100644 --- a/test/data/mock-state.json +++ b/test/data/mock-state.json @@ -115,13 +115,22 @@ "type": "rpc", "chainId": "0x5", "ticker": "ETH", - "id": "testNetworkConfigurationId" + "id": "chain5" }, "networkConfigurations": { "testNetworkConfigurationId": { "rpcUrl": "https://testrpc.com", "chainId": "0x1", - "nickname": "Custom Mainnet RPC" + "nickname": "Custom Mainnet RPC", + "type": "rpc", + "id": "testNetworkConfigurationId" + }, + "chain5": { + "type": "rpc", + "chainId": "0x5", + "ticker": "ETH", + "nickname": "Chain 5", + "id": "chain5" } }, "keyrings": [ diff --git a/test/e2e/fixture-builder.js b/test/e2e/fixture-builder.js index 884c9b94e..bbbcd49cf 100644 --- a/test/e2e/fixture-builder.js +++ b/test/e2e/fixture-builder.js @@ -215,6 +215,7 @@ function defaultFixture() { rpcUrl: 'http://localhost:8545', ticker: 'ETH', type: 'rpc', + id: 'networkConfigurationId', }, networkConfigurations: { networkConfigurationId: { @@ -346,6 +347,7 @@ function onboardingFixture() { rpcUrl: 'http://localhost:8545', chainId: CHAIN_IDS.LOCALHOST, nickname: 'Localhost 8545', + id: 'networkConfigurationId', }, networkConfigurations: { networkConfigurationId: { @@ -355,6 +357,7 @@ function onboardingFixture() { rpcUrl: 'http://localhost:8545', ticker: 'ETH', networkConfigurationId: 'networkConfigurationId', + type: 'rpc', }, }, }, diff --git a/test/e2e/tests/custom-rpc-history.spec.js b/test/e2e/tests/custom-rpc-history.spec.js index 8b43ab712..fd8e8314b 100644 --- a/test/e2e/tests/custom-rpc-history.spec.js +++ b/test/e2e/tests/custom-rpc-history.spec.js @@ -196,19 +196,21 @@ describe('Stores custom RPC history', function () { fixtures: new FixtureBuilder() .withNetworkController({ networkConfigurations: { - networkConfigurationId: { + networkConfigurationIdOne: { rpcUrl: 'http://127.0.0.1:8545/1', chainId: '0x539', ticker: 'ETH', nickname: 'http://127.0.0.1:8545/1', rpcPrefs: {}, + type: 'rpc', }, - networkConfigurationId2: { + networkConfigurationIdTwo: { rpcUrl: 'http://127.0.0.1:8545/2', chainId: '0x539', ticker: 'ETH', nickname: 'http://127.0.0.1:8545/2', rpcPrefs: {}, + type: 'rpc', }, }, }) @@ -248,14 +250,14 @@ describe('Stores custom RPC history', function () { fixtures: new FixtureBuilder() .withNetworkController({ networkConfigurations: { - networkConfigurationId: { + networkConfigurationIdOne: { rpcUrl: 'http://127.0.0.1:8545/1', chainId: '0x539', ticker: 'ETH', nickname: 'http://127.0.0.1:8545/1', rpcPrefs: {}, }, - networkConfigurationId2: { + networkConfigurationIdTwo: { rpcUrl: 'http://127.0.0.1:8545/2', chainId: '0x539', ticker: 'ETH', diff --git a/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap b/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap index 152b24ab7..30bdc2666 100644 --- a/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap +++ b/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap @@ -66,7 +66,7 @@ exports[`NFT Details should match minimal props and state snapshot 1`] = ` class="box mm-text mm-avatar-base mm-avatar-base--size-sm mm-avatar-network nft-item__network-badge mm-text--body-sm mm-text--text-transform-uppercase box--display-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-text-default box--background-color-background-alternative box--rounded-full box--border-color-background-default box--border-width-2 box--border-style-solid" data-testid="nft-network-badge" > - G + C
diff --git a/ui/components/app/nft-details/nft-details.test.js b/ui/components/app/nft-details/nft-details.test.js index 3909406b2..aab54bd60 100644 --- a/ui/components/app/nft-details/nft-details.test.js +++ b/ui/components/app/nft-details/nft-details.test.js @@ -13,6 +13,12 @@ import { removeAndIgnoreNft, setRemoveNftMessage, } from '../../../store/actions'; +import { + CHAIN_IDS, + CURRENCY_SYMBOLS, + MAINNET_DISPLAY_NAME, + NETWORK_TYPES, +} from '../../../../shared/constants/network'; import NftDetails from './nft-details'; jest.mock('copy-to-clipboard'); @@ -172,7 +178,10 @@ describe('NFT Details', () => { metamask: { ...mockState.metamask, providerConfig: { - chainId: '0x1', + chainId: CHAIN_IDS.MAINNET, + type: NETWORK_TYPES.MAINNET, + ticker: CURRENCY_SYMBOLS.ETH, + nickname: MAINNET_DISPLAY_NAME, }, }, }; @@ -203,12 +212,16 @@ describe('NFT Details', () => { ...mockState.metamask, providerConfig: { chainId: '0x89', + type: 'rpc', + id: 'custom-mainnet', }, networkConfigurations: { testNetworkConfigurationId: { rpcUrl: 'https://testrpc.com', chainId: '0x89', nickname: 'Custom Mainnet RPC', + type: 'rpc', + id: 'custom-mainnet', }, }, }, @@ -239,7 +252,8 @@ describe('NFT Details', () => { metamask: { ...mockState.metamask, providerConfig: { - chainId: '0xaa36a7', + chainId: CHAIN_IDS.SEPOLIA, + type: NETWORK_TYPES.SEPOLIA, }, }, }; diff --git a/ui/components/multichain/app-header/__snapshots__/app-header.test.js.snap b/ui/components/multichain/app-header/__snapshots__/app-header.test.js.snap index bb44e6a6f..3a4e81f7e 100644 --- a/ui/components/multichain/app-header/__snapshots__/app-header.test.js.snap +++ b/ui/components/multichain/app-header/__snapshots__/app-header.test.js.snap @@ -214,12 +214,12 @@ exports[`App Header should match snapshot 1`] = `
- G + C

- Goerli + Chain 5

{ const networks = useSelector(getAllEnabledNetworks); const showTestNetworks = useSelector(getShowTestNetworks); const currentChainId = useSelector(getCurrentChainId); + + const currentNetwork = useSelector(getCurrentNetwork); + const dispatch = useDispatch(); const history = useHistory(); const trackEvent = useContext(MetaMetricsContext); @@ -91,7 +95,7 @@ export const NetworkListMenu = ({ onClose }) => { ) { return null; } - const isCurrentNetwork = currentChainId === network.chainId; + const isCurrentNetwork = currentNetwork.id === network.id; const canDeleteNetwork = !isCurrentNetwork && !UNREMOVABLE_CHAIN_IDS.includes(network.chainId); diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index 04517c7e0..a07c73788 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -1170,9 +1170,13 @@ export function getNetworkConfigurations(state) { export function getCurrentNetwork(state) { const allNetworks = getAllNetworks(state); - const currentChainId = getCurrentChainId(state); + const providerConfig = getProviderConfig(state); - return allNetworks.find((network) => network.chainId === currentChainId); + const filter = + providerConfig.type === 'rpc' + ? (network) => network.id === providerConfig.id + : (network) => network.id === providerConfig.type; + return allNetworks.find(filter); } export function getAllEnabledNetworks(state) { @@ -1200,6 +1204,7 @@ export function getAllNetworks(state) { }, providerType: NETWORK_TYPES.MAINNET, ticker: CURRENCY_SYMBOLS.ETH, + id: NETWORK_TYPES.MAINNET, }, { chainId: CHAIN_IDS.LINEA_MAINNET, @@ -1210,6 +1215,7 @@ export function getAllNetworks(state) { }, providerType: NETWORK_TYPES.LINEA_MAINNET, ticker: TEST_NETWORK_TICKER_MAP[NETWORK_TYPES.LINEA_MAINNET], + id: NETWORK_TYPES.LINEA_MAINNET, }, // Custom networks added by the user ...Object.values(networkConfigurations).filter( @@ -1222,6 +1228,7 @@ export function getAllNetworks(state) { rpcUrl: CHAIN_ID_TO_RPC_URL_MAP[CHAIN_IDS.GOERLI], providerType: NETWORK_TYPES.GOERLI, ticker: TEST_NETWORK_TICKER_MAP[NETWORK_TYPES.GOERLI], + id: NETWORK_TYPES.GOERLI, }, { chainId: CHAIN_IDS.SEPOLIA, @@ -1229,6 +1236,7 @@ export function getAllNetworks(state) { rpcUrl: CHAIN_ID_TO_RPC_URL_MAP[CHAIN_IDS.SEPOLIA], providerType: NETWORK_TYPES.SEPOLIA, ticker: TEST_NETWORK_TICKER_MAP[NETWORK_TYPES.SEPOLIA], + id: NETWORK_TYPES.SEPOLIA, }, { chainId: CHAIN_IDS.LINEA_GOERLI, @@ -1239,6 +1247,7 @@ export function getAllNetworks(state) { }, providerType: NETWORK_TYPES.LINEA_GOERLI, ticker: TEST_NETWORK_TICKER_MAP[NETWORK_TYPES.LINEA_GOERLI], + id: NETWORK_TYPES.LINEA_GOERLI, }, // Localhosts ...Object.values(networkConfigurations).filter( diff --git a/ui/selectors/selectors.test.js b/ui/selectors/selectors.test.js index 8819a9769..1c2b1b5de 100644 --- a/ui/selectors/selectors.test.js +++ b/ui/selectors/selectors.test.js @@ -316,6 +316,46 @@ describe('Selectors', () => { }); }); + describe('#getCurrentNetwork', () => { + it('returns the correct custom network when there is a chainId collision', () => { + const modifiedMockState = { + ...mockState, + metamask: { + ...mockState.metamask, + providerConfig: { + ...mockState.metamask.networkConfigurations + .testNetworkConfigurationId, + // 0x1 would collide with Ethereum Mainnet + chainId: '0x1', + // type of "rpc" signals custom network + type: 'rpc', + }, + }, + }; + + const currentNetwork = selectors.getCurrentNetwork(modifiedMockState); + expect(currentNetwork.nickname).toBe('Custom Mainnet RPC'); + expect(currentNetwork.chainId).toBe('0x1'); + }); + + it('returns the correct mainnet network when there is a chainId collision', () => { + const modifiedMockState = { + ...mockState, + metamask: { + ...mockState.metamask, + providerConfig: { + ...mockState.metamask.providerConfig, + chainId: '0x1', + // Changing type to 'mainnet' represents Ethereum Mainnet + type: 'mainnet', + }, + }, + }; + const currentNetwork = selectors.getCurrentNetwork(modifiedMockState); + expect(currentNetwork.nickname).toBe('Ethereum Mainnet'); + }); + }); + describe('#getAllEnabledNetworks', () => { it('returns only MainNet with showTestNetworks off', () => { const networks = selectors.getAllEnabledNetworks({ diff --git a/ui/store/actions.ts b/ui/store/actions.ts index 5e12c3ae7..509127bf6 100644 --- a/ui/store/actions.ts +++ b/ui/store/actions.ts @@ -19,12 +19,9 @@ import { PayloadAction } from '@reduxjs/toolkit'; import { GasFeeController } from '@metamask/gas-fee-controller'; import { PermissionsRequest } from '@metamask/permission-controller'; import { NonEmptyArray } from '@metamask/controller-utils'; -<<<<<<< HEAD ///: BEGIN:ONLY_INCLUDE_IN(keyring-snaps) import { HandlerType } from '@metamask/snaps-utils'; ///: END:ONLY_INCLUDE_IN -======= ->>>>>>> master import { getMethodDataAsync } from '../helpers/utils/transactions.util'; import switchDirection from '../../shared/lib/switch-direction'; import { From c9d2e61400ce41d070ecf3e7456ad44815a7b3ef Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Fri, 7 Jul 2023 11:14:18 -0700 Subject: [PATCH 043/172] Bump @metamask/network-controller to 10.3.0 (#19903) In the new version of NetworkController, it will now precreate network clients for built-in and custom networks and expose those network clients for consumers. This furthers the multichain UX project by making it possible for MetaMask to interface with multiple networks simultaneously. This commit also upgrades `@metamask/gas-fee-controller` to prevent a peer dependency warning from showing up as well as `@metamask/controller-utils` in order to reduce the dependency tree. There are no user-facing changes to either package. --- .iyarc | 4 +--- package.json | 8 +++---- yarn.lock | 63 +++++++++++++++++----------------------------------- 3 files changed, 25 insertions(+), 50 deletions(-) diff --git a/.iyarc b/.iyarc index 0bb3e981f..cea1e59eb 100644 --- a/.iyarc +++ b/.iyarc @@ -3,6 +3,4 @@ GHSA-257v-vj4p-3w2h # request library is subject to SSRF. # addressed by temporary patch in .yarn/patches/request-npm-2.88.2-f4a57c72c4.patch -# NOTE: Disabled for now since this library seems to have been removed from the -# dependency tree — we can re-enable this line later if it appears again -#GHSA-p8p7-x288-28g6 +GHSA-p8p7-x288-28g6 diff --git a/package.json b/package.json index fee7bf4ed..c067fb97d 100644 --- a/package.json +++ b/package.json @@ -230,8 +230,8 @@ "@metamask/base-controller": "^3.1.0", "@metamask/browser-passworder": "^4.1.0", "@metamask/contract-metadata": "^2.3.1", - "@metamask/controller-utils": "^4.0.1", - "@metamask/design-tokens": "^1.9.0", + "@metamask/controller-utils": "^4.1.0", + "@metamask/design-tokens": "^1.12.0", "@metamask/desktop": "^0.3.0", "@metamask/eth-json-rpc-middleware": "^11.0.0", "@metamask/eth-keyring-controller": "^10.0.1", @@ -240,13 +240,13 @@ "@metamask/eth-token-tracker": "^4.0.0", "@metamask/eth-trezor-keyring": "^1.0.0", "@metamask/etherscan-link": "^2.2.0", - "@metamask/gas-fee-controller": "^6.0.0", + "@metamask/gas-fee-controller": "^6.0.1", "@metamask/jazzicon": "^2.0.0", "@metamask/key-tree": "^7.0.0", "@metamask/logo": "^3.1.1", "@metamask/message-manager": "^7.0.2", "@metamask/metamask-eth-abis": "^3.0.0", - "@metamask/network-controller": "^10.1.0", + "@metamask/network-controller": "^10.3.0", "@metamask/notification-controller": "^3.0.0", "@metamask/obs-store": "^8.1.0", "@metamask/permission-controller": "^4.0.0", diff --git a/yarn.lock b/yarn.lock index c88669224..64cb5026d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4024,10 +4024,10 @@ __metadata: languageName: node linkType: hard -"@metamask/design-tokens@npm:^1.6.0, @metamask/design-tokens@npm:^1.9.0": - version: 1.11.1 - resolution: "@metamask/design-tokens@npm:1.11.1" - checksum: 38677f66167861826c35f7b0e6efc3c69269178e3dad5de41a9c9a7925dfb1f560f673e02a51acd7f7983762546130132f83dcaefe8ab47e16301775cff0b968 +"@metamask/design-tokens@npm:^1.12.0, @metamask/design-tokens@npm:^1.6.0": + version: 1.12.0 + resolution: "@metamask/design-tokens@npm:1.12.0" + checksum: 9b6c5485c846171aa7fcef03cbe93b4d94ffaa76faf953aa27a689fd3d494438cd657de6ea1aa5a40cc2af15dcf10f8dd860fd3d90f5e9806807e37020bdccd9 languageName: node linkType: hard @@ -4285,13 +4285,13 @@ __metadata: languageName: node linkType: hard -"@metamask/gas-fee-controller@npm:^6.0.0": - version: 6.0.0 - resolution: "@metamask/gas-fee-controller@npm:6.0.0" +"@metamask/gas-fee-controller@npm:^6.0.1": + version: 6.0.1 + resolution: "@metamask/gas-fee-controller@npm:6.0.1" dependencies: "@metamask/base-controller": ^3.0.0 - "@metamask/controller-utils": ^4.0.0 - "@metamask/network-controller": ^9.0.0 + "@metamask/controller-utils": ^4.1.0 + "@metamask/network-controller": ^10.3.0 "@metamask/utils": ^5.0.2 "@types/uuid": ^8.3.0 babel-runtime: ^6.26.0 @@ -4301,8 +4301,8 @@ __metadata: immer: ^9.0.6 uuid: ^8.3.2 peerDependencies: - "@metamask/network-controller": ^9.0.0 - checksum: e7f15b0d3043e228f85cfa462c800d7332845b8d13211b1688c68a3b4b09b921aaa9b3304688dd0b7e4d9abd59f96dab0f50259a90f35c4b50321e2805c65bfb + "@metamask/network-controller": ^10.3.0 + checksum: 4a9243ee6aad355b4f2ef1a1065f1444f823721a02af2e8a8f35683f60f020a280f33be15bce95b24c4aff698408aaa263070bec020019b8bef561d55bdc949c languageName: node linkType: hard @@ -4378,12 +4378,12 @@ __metadata: languageName: node linkType: hard -"@metamask/network-controller@npm:^10.1.0, @metamask/network-controller@npm:^10.2.0": - version: 10.2.0 - resolution: "@metamask/network-controller@npm:10.2.0" +"@metamask/network-controller@npm:^10.2.0, @metamask/network-controller@npm:^10.3.0": + version: 10.3.0 + resolution: "@metamask/network-controller@npm:10.3.0" dependencies: "@metamask/base-controller": ^3.0.0 - "@metamask/controller-utils": ^4.0.1 + "@metamask/controller-utils": ^4.1.0 "@metamask/eth-json-rpc-infura": ^8.0.0 "@metamask/eth-json-rpc-middleware": ^11.0.0 "@metamask/eth-json-rpc-provider": ^1.0.0 @@ -4397,7 +4397,7 @@ __metadata: immer: ^9.0.6 json-rpc-engine: ^6.1.0 uuid: ^8.3.2 - checksum: 6474125845d838564ef60105b5914369aa650a6769df5f3f2a471839f351d798984faa5e3184054a5bfb4ec738e2a50c6fbf31f9eceb9cea4c227651105295dc + checksum: 0c48625af9c18be3ed2a433209db770bab02e667e251be1ef4c1f61a62c25907536ff740712bdfd799ac923a4a6bb9df5430ead8d4215507bbf30dcc7a40d53c languageName: node linkType: hard @@ -4417,29 +4417,6 @@ __metadata: languageName: node linkType: hard -"@metamask/network-controller@npm:^9.0.0": - version: 9.0.0 - resolution: "@metamask/network-controller@npm:9.0.0" - dependencies: - "@metamask/base-controller": ^3.0.0 - "@metamask/controller-utils": ^4.0.0 - "@metamask/eth-json-rpc-infura": ^8.0.0 - "@metamask/eth-json-rpc-middleware": ^11.0.0 - "@metamask/eth-json-rpc-provider": ^1.0.0 - "@metamask/swappable-obj-proxy": ^2.1.0 - "@metamask/utils": ^5.0.2 - async-mutex: ^0.2.6 - babel-runtime: ^6.26.0 - eth-block-tracker: ^7.0.1 - eth-query: ^2.1.2 - eth-rpc-errors: ^4.0.2 - immer: ^9.0.6 - json-rpc-engine: ^6.1.0 - uuid: ^8.3.2 - checksum: 7548fe82990ff62d36a6c42a49442422fe3634933b6fc85b86a3bbb2788a755c73f3fa70a70ae48ddf09a70e3e33d375723980aec76e89cdf21b76b96a069b07 - languageName: node - linkType: hard - "@metamask/notification-controller@npm:^3.0.0": version: 3.0.0 resolution: "@metamask/notification-controller@npm:3.0.0" @@ -24507,8 +24484,8 @@ __metadata: "@metamask/base-controller": ^3.1.0 "@metamask/browser-passworder": ^4.1.0 "@metamask/contract-metadata": ^2.3.1 - "@metamask/controller-utils": ^4.0.1 - "@metamask/design-tokens": ^1.9.0 + "@metamask/controller-utils": ^4.1.0 + "@metamask/design-tokens": ^1.12.0 "@metamask/desktop": ^0.3.0 "@metamask/eslint-config": ^9.0.0 "@metamask/eslint-config-jest": ^9.0.0 @@ -24523,13 +24500,13 @@ __metadata: "@metamask/eth-trezor-keyring": ^1.0.0 "@metamask/etherscan-link": ^2.2.0 "@metamask/forwarder": ^1.1.0 - "@metamask/gas-fee-controller": ^6.0.0 + "@metamask/gas-fee-controller": ^6.0.1 "@metamask/jazzicon": ^2.0.0 "@metamask/key-tree": ^7.0.0 "@metamask/logo": ^3.1.1 "@metamask/message-manager": ^7.0.2 "@metamask/metamask-eth-abis": ^3.0.0 - "@metamask/network-controller": ^10.1.0 + "@metamask/network-controller": ^10.3.0 "@metamask/notification-controller": ^3.0.0 "@metamask/obs-store": ^8.1.0 "@metamask/permission-controller": ^4.0.0 From ccc4cf1bb97e7ae7f3f9b0ba50b7d3feac5846d9 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Mon, 10 Jul 2023 12:56:34 -0230 Subject: [PATCH 044/172] Resolve two new security advisories (#19940) Two new security advisories have been resolved. These advisories are causing CI to fail on `develop`. Neither presents any risk to us, as they are prototype pollution issues that are prevented by lockdown. The first advisory isn't easy for us to patch. It's caused by an outdated version of `protobufjs` used by `@trezor/transport`. It has been ignored for now, until Trezor updates that package. For the second advisory (related to `tough-cookie`), it was resolved by updating that dependency in our lockfile. --- .iyarc | 5 +++++ yarn.lock | 42 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/.iyarc b/.iyarc index cea1e59eb..9e16de044 100644 --- a/.iyarc +++ b/.iyarc @@ -4,3 +4,8 @@ GHSA-257v-vj4p-3w2h # request library is subject to SSRF. # addressed by temporary patch in .yarn/patches/request-npm-2.88.2-f4a57c72c4.patch GHSA-p8p7-x288-28g6 + +# Prototype pollution +# Not easily patched +# Minimal risk to us because we're using lockdown which also prevents this case of prototype pollution +GHSA-h755-8qp9-cq85 diff --git a/yarn.lock b/yarn.lock index 64cb5026d..bccbec8fe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -28818,6 +28818,13 @@ __metadata: languageName: node linkType: hard +"querystringify@npm:^2.1.1": + version: 2.2.0 + resolution: "querystringify@npm:2.2.0" + checksum: 5641ea231bad7ef6d64d9998faca95611ed4b11c2591a8cae741e178a974f6a8e0ebde008475259abe1621cb15e692404e6b6626e927f7b849d5c09392604b15 + languageName: node + linkType: hard + "queue-microtask@npm:^1.2.3": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -30320,6 +30327,13 @@ __metadata: languageName: node linkType: hard +"requires-port@npm:^1.0.0": + version: 1.0.0 + resolution: "requires-port@npm:1.0.0" + checksum: eee0e303adffb69be55d1a214e415cf42b7441ae858c76dfc5353148644f6fd6e698926fc4643f510d5c126d12a705e7c8ed7e38061113bdf37547ab356797ff + languageName: node + linkType: hard + "reselect@npm:^3.0.1": version: 3.0.1 resolution: "reselect@npm:3.0.1" @@ -33418,13 +33432,14 @@ __metadata: linkType: hard "tough-cookie@npm:>=2.3.3, tough-cookie@npm:^4.0.0": - version: 4.0.0 - resolution: "tough-cookie@npm:4.0.0" + version: 4.1.3 + resolution: "tough-cookie@npm:4.1.3" dependencies: psl: ^1.1.33 punycode: ^2.1.1 - universalify: ^0.1.2 - checksum: 0891b37eb7d17faa3479d47f0dce2e3007f2583094ad272f2670d120fbcc3df3b0b0a631ba96ecad49f9e2297d93ff8995ce0d3292d08dd7eabe162f5b224d69 + universalify: ^0.2.0 + url-parse: ^1.5.3 + checksum: c9226afff36492a52118432611af083d1d8493a53ff41ec4ea48e5b583aec744b989e4280bcf476c910ec1525a89a4a0f1cae81c08b18fb2ec3a9b3a72b91dcc languageName: node linkType: hard @@ -34316,13 +34331,20 @@ __metadata: languageName: node linkType: hard -"universalify@npm:^0.1.0, universalify@npm:^0.1.2": +"universalify@npm:^0.1.0": version: 0.1.2 resolution: "universalify@npm:0.1.2" checksum: 40cdc60f6e61070fe658ca36016a8f4ec216b29bf04a55dce14e3710cc84c7448538ef4dad3728d0bfe29975ccd7bfb5f414c45e7b78883567fb31b246f02dff languageName: node linkType: hard +"universalify@npm:^0.2.0": + version: 0.2.0 + resolution: "universalify@npm:0.2.0" + checksum: e86134cb12919d177c2353196a4cc09981524ee87abf621f7bc8d249dbbbebaec5e7d1314b96061497981350df786e4c5128dbf442eba104d6e765bc260678b5 + languageName: node + linkType: hard + "universalify@npm:^2.0.0": version: 2.0.0 resolution: "universalify@npm:2.0.0" @@ -34478,6 +34500,16 @@ __metadata: languageName: node linkType: hard +"url-parse@npm:^1.5.3": + version: 1.5.10 + resolution: "url-parse@npm:1.5.10" + dependencies: + querystringify: ^2.1.1 + requires-port: ^1.0.0 + checksum: fbdba6b1d83336aca2216bbdc38ba658d9cfb8fc7f665eb8b17852de638ff7d1a162c198a8e4ed66001ddbf6c9888d41e4798912c62b4fd777a31657989f7bdf + languageName: node + linkType: hard + "url@npm:~0.11.0": version: 0.11.0 resolution: "url@npm:0.11.0" From 65946c47c434fd9493b0f9e29a83198ffab70ed5 Mon Sep 17 00:00:00 2001 From: Elliot Winkler Date: Thu, 13 Jul 2023 16:57:31 -0600 Subject: [PATCH 045/172] Restore support for Linea networks (#20011) When the NetworkController in this repo was replaced with `@metamask/network-controller`, support for Linea networks was lost as it did not support it at that time. `@metamask/network-controller` has since been updated, so this commit bumps that package to restore support. --- .iyarc | 4 ++ lavamoat/browserify/beta/policy.json | 22 +------- lavamoat/browserify/desktop/policy.json | 22 +------- lavamoat/browserify/flask/policy.json | 22 +------- lavamoat/browserify/main/policy.json | 22 +------- lavamoat/browserify/mmi/policy.json | 22 +------- package.json | 4 +- yarn.lock | 71 +++++++++++-------------- 8 files changed, 43 insertions(+), 146 deletions(-) diff --git a/.iyarc b/.iyarc index 9e16de044..2b0adcf36 100644 --- a/.iyarc +++ b/.iyarc @@ -9,3 +9,7 @@ GHSA-p8p7-x288-28g6 # Not easily patched # Minimal risk to us because we're using lockdown which also prevents this case of prototype pollution GHSA-h755-8qp9-cq85 + +# tough-cookie +# this will go away soon when we get rid of web3-provider-engine +GHSA-72xf-g2v4-qvf3 diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index 4990fb1b9..8231a9ec8 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -1621,7 +1621,7 @@ }, "packages": { "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": true, + "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, "eth-rpc-errors": true, "json-rpc-engine": true, "node-fetch": true @@ -1639,26 +1639,6 @@ "superstruct": true } }, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": { - "globals": { - "URL": true, - "btoa": true, - "console.error": true, - "fetch": true, - "setTimeout": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/eth-sig-util": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>pify": true, - "@metamask/safe-event-emitter": true, - "browserify>browser-resolve": true, - "eth-rpc-errors": true, - "json-rpc-engine": true, - "lavamoat>json-stable-stringify": true, - "vinyl>clone": true - } - }, "@metamask/network-controller>@metamask/eth-json-rpc-provider": { "packages": { "@metamask/safe-event-emitter": true, diff --git a/lavamoat/browserify/desktop/policy.json b/lavamoat/browserify/desktop/policy.json index 6cd8068ff..7428fea81 100644 --- a/lavamoat/browserify/desktop/policy.json +++ b/lavamoat/browserify/desktop/policy.json @@ -1747,7 +1747,7 @@ }, "packages": { "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": true, + "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, "eth-rpc-errors": true, "json-rpc-engine": true, "node-fetch": true @@ -1765,26 +1765,6 @@ "superstruct": true } }, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": { - "globals": { - "URL": true, - "btoa": true, - "console.error": true, - "fetch": true, - "setTimeout": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/eth-sig-util": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>pify": true, - "@metamask/safe-event-emitter": true, - "browserify>browser-resolve": true, - "eth-rpc-errors": true, - "json-rpc-engine": true, - "lavamoat>json-stable-stringify": true, - "vinyl>clone": true - } - }, "@metamask/network-controller>@metamask/eth-json-rpc-provider": { "packages": { "@metamask/safe-event-emitter": true, diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index 6cd8068ff..7428fea81 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -1747,7 +1747,7 @@ }, "packages": { "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": true, + "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, "eth-rpc-errors": true, "json-rpc-engine": true, "node-fetch": true @@ -1765,26 +1765,6 @@ "superstruct": true } }, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": { - "globals": { - "URL": true, - "btoa": true, - "console.error": true, - "fetch": true, - "setTimeout": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/eth-sig-util": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>pify": true, - "@metamask/safe-event-emitter": true, - "browserify>browser-resolve": true, - "eth-rpc-errors": true, - "json-rpc-engine": true, - "lavamoat>json-stable-stringify": true, - "vinyl>clone": true - } - }, "@metamask/network-controller>@metamask/eth-json-rpc-provider": { "packages": { "@metamask/safe-event-emitter": true, diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index 4990fb1b9..8231a9ec8 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -1621,7 +1621,7 @@ }, "packages": { "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": true, + "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, "eth-rpc-errors": true, "json-rpc-engine": true, "node-fetch": true @@ -1639,26 +1639,6 @@ "superstruct": true } }, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": { - "globals": { - "URL": true, - "btoa": true, - "console.error": true, - "fetch": true, - "setTimeout": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/eth-sig-util": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>pify": true, - "@metamask/safe-event-emitter": true, - "browserify>browser-resolve": true, - "eth-rpc-errors": true, - "json-rpc-engine": true, - "lavamoat>json-stable-stringify": true, - "vinyl>clone": true - } - }, "@metamask/network-controller>@metamask/eth-json-rpc-provider": { "packages": { "@metamask/safe-event-emitter": true, diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index 79411ecd1..9dabc001b 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -1842,7 +1842,7 @@ }, "packages": { "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": true, + "@metamask/network-controller>@metamask/eth-json-rpc-provider": true, "eth-rpc-errors": true, "json-rpc-engine": true, "node-fetch": true @@ -1860,26 +1860,6 @@ "superstruct": true } }, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": { - "globals": { - "URL": true, - "btoa": true, - "console.error": true, - "fetch": true, - "setTimeout": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/eth-sig-util": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/utils": true, - "@metamask/network-controller>@metamask/eth-json-rpc-infura>eth-json-rpc-middleware>pify": true, - "@metamask/safe-event-emitter": true, - "browserify>browser-resolve": true, - "eth-rpc-errors": true, - "json-rpc-engine": true, - "lavamoat>json-stable-stringify": true, - "vinyl>clone": true - } - }, "@metamask/network-controller>@metamask/eth-json-rpc-provider": { "packages": { "@metamask/safe-event-emitter": true, diff --git a/package.json b/package.json index c067fb97d..a830bca0c 100644 --- a/package.json +++ b/package.json @@ -230,7 +230,7 @@ "@metamask/base-controller": "^3.1.0", "@metamask/browser-passworder": "^4.1.0", "@metamask/contract-metadata": "^2.3.1", - "@metamask/controller-utils": "^4.1.0", + "@metamask/controller-utils": "^4.2.0", "@metamask/design-tokens": "^1.12.0", "@metamask/desktop": "^0.3.0", "@metamask/eth-json-rpc-middleware": "^11.0.0", @@ -246,7 +246,7 @@ "@metamask/logo": "^3.1.1", "@metamask/message-manager": "^7.0.2", "@metamask/metamask-eth-abis": "^3.0.0", - "@metamask/network-controller": "^10.3.0", + "@metamask/network-controller": "^10.3.1", "@metamask/notification-controller": "^3.0.0", "@metamask/obs-store": "^8.1.0", "@metamask/permission-controller": "^4.0.0", diff --git a/yarn.lock b/yarn.lock index bccbec8fe..a47b620aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4007,9 +4007,9 @@ __metadata: languageName: node linkType: hard -"@metamask/controller-utils@npm:^4.0.0, @metamask/controller-utils@npm:^4.0.1, @metamask/controller-utils@npm:^4.1.0": - version: 4.1.0 - resolution: "@metamask/controller-utils@npm:4.1.0" +"@metamask/controller-utils@npm:^4.0.0, @metamask/controller-utils@npm:^4.0.1, @metamask/controller-utils@npm:^4.1.0, @metamask/controller-utils@npm:^4.2.0": + version: 4.2.0 + resolution: "@metamask/controller-utils@npm:4.2.0" dependencies: "@metamask/utils": ^5.0.2 "@spruceid/siwe-parser": 1.1.3 @@ -4020,7 +4020,7 @@ __metadata: ethereumjs-util: ^7.0.10 ethjs-unit: ^0.1.6 fast-deep-equal: ^3.1.3 - checksum: b4975e6ca860b691931254aa749e8c4faddd04279609cf197155b38150e55da0e966bf9b2d61ee1cd070f79d16e0305d5a0ff1747e0b4ab2e1c3ab46ca84e4d7 + checksum: e71779577c37038e6e605a43ef6b9c1af82e0b3887a72c01f48ae1e4e2005116fc9d09c8b690139478c04dd2929e227642c5fd80cfbc81814d667c415c714228 languageName: node linkType: hard @@ -4121,16 +4121,16 @@ __metadata: languageName: node linkType: hard -"@metamask/eth-json-rpc-infura@npm:^8.0.0": - version: 8.1.0 - resolution: "@metamask/eth-json-rpc-infura@npm:8.1.0" +"@metamask/eth-json-rpc-infura@npm:^8.1.0": + version: 8.1.1 + resolution: "@metamask/eth-json-rpc-infura@npm:8.1.1" dependencies: - "@metamask/utils": ^3.0.1 - eth-json-rpc-middleware: ^9.0.0 + "@metamask/eth-json-rpc-provider": ^1.0.0 + "@metamask/utils": ^4.0.0 eth-rpc-errors: ^4.0.3 json-rpc-engine: ^6.1.0 node-fetch: ^2.6.7 - checksum: fd09383e2b3c16187b8889b53bfc431fc7ea4f6483acc23ddf77f2fd771ad0fbff41d6a62d4b05833e7cda66adafe0cb3730d7c0e9575b89683b71a82ab1ee1f + checksum: ab4ce53fcc1586344824d58aed4d71412b015466f697758b4849e186038ae1730c9765935dfaf1a9131ff1a8f0f36dcb66fd50355ed95ac7a4bf0bc18c4c2696 languageName: node linkType: hard @@ -4378,13 +4378,13 @@ __metadata: languageName: node linkType: hard -"@metamask/network-controller@npm:^10.2.0, @metamask/network-controller@npm:^10.3.0": - version: 10.3.0 - resolution: "@metamask/network-controller@npm:10.3.0" +"@metamask/network-controller@npm:^10.2.0, @metamask/network-controller@npm:^10.3.0, @metamask/network-controller@npm:^10.3.1": + version: 10.3.1 + resolution: "@metamask/network-controller@npm:10.3.1" dependencies: - "@metamask/base-controller": ^3.0.0 - "@metamask/controller-utils": ^4.1.0 - "@metamask/eth-json-rpc-infura": ^8.0.0 + "@metamask/base-controller": ^3.1.0 + "@metamask/controller-utils": ^4.2.0 + "@metamask/eth-json-rpc-infura": ^8.1.0 "@metamask/eth-json-rpc-middleware": ^11.0.0 "@metamask/eth-json-rpc-provider": ^1.0.0 "@metamask/swappable-obj-proxy": ^2.1.0 @@ -4397,7 +4397,7 @@ __metadata: immer: ^9.0.6 json-rpc-engine: ^6.1.0 uuid: ^8.3.2 - checksum: 0c48625af9c18be3ed2a433209db770bab02e667e251be1ef4c1f61a62c25907536ff740712bdfd799ac923a4a6bb9df5430ead8d4215507bbf30dcc7a40d53c + checksum: 62adb90b02eae1236f9c1c3ceb70c9de0f4e390c3b68ced0c81b0b867dced7814d5d805cdfb6e0ccc9e62b82fac762f70c204f08feb3f3ee5647610d079cbdd7 languageName: node linkType: hard @@ -4968,7 +4968,7 @@ __metadata: languageName: node linkType: hard -"@metamask/utils@npm:^3.0.1, @metamask/utils@npm:^3.0.3, @metamask/utils@npm:^3.4.1": +"@metamask/utils@npm:^3.0.3, @metamask/utils@npm:^3.4.1": version: 3.6.0 resolution: "@metamask/utils@npm:3.6.0" dependencies: @@ -4980,6 +4980,18 @@ __metadata: languageName: node linkType: hard +"@metamask/utils@npm:^4.0.0": + version: 4.0.0 + resolution: "@metamask/utils@npm:4.0.0" + dependencies: + "@types/debug": ^4.1.7 + debug: ^4.3.4 + semver: ^7.3.8 + superstruct: ^1.0.3 + checksum: 6d4edca78fe1f66504ed5e5ca021a67f4b4e0893e86484c746b87039c2161c39d3b8bd8e4b9235ddfd023b2d76dd54210af94ec5550e27bc4ad9c0d7d5f3f231 + languageName: node + linkType: hard + "@metamask/utils@npm:^5.0.0, @metamask/utils@npm:^5.0.1, @metamask/utils@npm:^5.0.2": version: 5.0.2 resolution: "@metamask/utils@npm:5.0.2" @@ -15997,25 +16009,6 @@ __metadata: languageName: node linkType: hard -"eth-json-rpc-middleware@npm:^9.0.0": - version: 9.0.1 - resolution: "eth-json-rpc-middleware@npm:9.0.1" - dependencies: - "@metamask/eth-sig-util": ^5.0.0 - "@metamask/safe-event-emitter": ^2.0.0 - "@metamask/utils": ^3.0.3 - btoa: ^1.2.1 - clone: ^2.1.1 - eth-block-tracker: ^5.0.1 - eth-rpc-errors: ^4.0.3 - json-rpc-engine: ^6.1.0 - json-stable-stringify: ^1.0.1 - node-fetch: ^2.6.7 - pify: ^3.0.0 - checksum: 9512829a6958df6ef739b891a0c0804b51a140407fd2e3ddaaa6b18d975796646cfcf7f7305a18beb7903db09e0c7a91b06dc5434b6bd2d6cdb85d992d9fd3ab - languageName: node - linkType: hard - "eth-lattice-keyring@npm:^0.12.4": version: 0.12.4 resolution: "eth-lattice-keyring@npm:0.12.4" @@ -24484,7 +24477,7 @@ __metadata: "@metamask/base-controller": ^3.1.0 "@metamask/browser-passworder": ^4.1.0 "@metamask/contract-metadata": ^2.3.1 - "@metamask/controller-utils": ^4.1.0 + "@metamask/controller-utils": ^4.2.0 "@metamask/design-tokens": ^1.12.0 "@metamask/desktop": ^0.3.0 "@metamask/eslint-config": ^9.0.0 @@ -24506,7 +24499,7 @@ __metadata: "@metamask/logo": ^3.1.1 "@metamask/message-manager": ^7.0.2 "@metamask/metamask-eth-abis": ^3.0.0 - "@metamask/network-controller": ^10.3.0 + "@metamask/network-controller": ^10.3.1 "@metamask/notification-controller": ^3.0.0 "@metamask/obs-store": ^8.1.0 "@metamask/permission-controller": ^4.0.0 From c25d47952ee01536021738b862bbfe5238fea84b Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Fri, 14 Jul 2023 09:35:05 -0230 Subject: [PATCH 046/172] Remove failing audit exclusion for GHSA-h755-8qp9-cq85 --- .iyarc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.iyarc b/.iyarc index 2b0adcf36..9e16de044 100644 --- a/.iyarc +++ b/.iyarc @@ -9,7 +9,3 @@ GHSA-p8p7-x288-28g6 # Not easily patched # Minimal risk to us because we're using lockdown which also prevents this case of prototype pollution GHSA-h755-8qp9-cq85 - -# tough-cookie -# this will go away soon when we get rid of web3-provider-engine -GHSA-72xf-g2v4-qvf3 From 91c84996b7053e63df282e1e1c982bc237f54b38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Oliv=C3=A9?= Date: Fri, 14 Jul 2023 15:02:00 +0200 Subject: [PATCH 047/172] =?UTF-8?q?[MMI]=C2=A0Added=20missing=20locales=20?= =?UTF-8?q?(#20024)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added missing locales * Added missing locale --- app/_locales/en/messages.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index dac6a5634..fd9c12b64 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -528,6 +528,9 @@ "message": "This is a beta version. Please report bugs $1", "description": "$1 represents the word 'here' in a hyperlink" }, + "betaMetamaskInstitutionalVersion": { + "message": "MetaMask Institutional Beta Version" + }, "betaMetamaskVersion": { "message": "MetaMask Beta Version" }, @@ -2268,6 +2271,9 @@ "metaMaskConnectStatusParagraphTwo": { "message": "The connection status button shows if the website you’re visiting is connected to your currently selected account." }, + "metamaskInstitutionalVersion": { + "message": "MetaMask Institutional Version" + }, "metamaskSwapsOfflineDescription": { "message": "MetaMask Swaps is undergoing maintenance. Please check back later." }, @@ -2312,6 +2318,9 @@ "mmiAuthenticate": { "message": "The page at $1 would like to authorise the following project’s compliance settings in MetaMask Institutional" }, + "mmiBuiltAroundTheWorld": { + "message": "MetaMask Institutional is designed and built around the world." + }, "more": { "message": "more" }, From 45b7b0ca762d7fd7e8d6c6c026732b6169db713f Mon Sep 17 00:00:00 2001 From: David Walsh Date: Fri, 14 Jul 2023 08:21:53 -0500 Subject: [PATCH 048/172] UX: Network Menu: Disable testnet toggle when on testnet (#19951) --- .../network-list-menu/network-list-menu.js | 11 +++++------ .../network-list-menu/network-list-menu.test.js | 12 +++++++++++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/ui/components/multichain/network-list-menu/network-list-menu.js b/ui/components/multichain/network-list-menu/network-list-menu.js index 4b7cb83f0..0006a332e 100644 --- a/ui/components/multichain/network-list-menu/network-list-menu.js +++ b/ui/components/multichain/network-list-menu/network-list-menu.js @@ -17,7 +17,6 @@ import { getCurrentChainId, getNonTestNetworks, getTestNetworks, - getCurrentNetwork, } from '../../../selectors'; import ToggleButton from '../../ui/toggle-button'; import { @@ -58,16 +57,15 @@ export const NetworkListMenu = ({ onClose }) => { const nonTestNetworks = useSelector(getNonTestNetworks); const testNetworks = useSelector(getTestNetworks); - const showTestNetworks = useSelector(getShowTestNetworks); const currentChainId = useSelector(getCurrentChainId); - const currentNetwork = useSelector(getCurrentNetwork); - const dispatch = useDispatch(); const history = useHistory(); const trackEvent = useContext(MetaMetricsContext); + const currentlyOnTestNetwork = TEST_CHAINS.includes(currentChainId); + const environmentType = getEnvironmentType(); const isFullScreen = environmentType === ENVIRONMENT_TYPE_FULLSCREEN; @@ -80,8 +78,8 @@ export const NetworkListMenu = ({ onClose }) => { if (!lineaMainnetReleased && network.providerType === 'linea-mainnet') { return null; } - const isCurrentNetwork = currentNetwork.id === network.id; + const isCurrentNetwork = currentChainId === network.chainId; const canDeleteNetwork = !isCurrentNetwork && !UNREMOVABLE_CHAIN_IDS.includes(network.chainId); @@ -155,6 +153,7 @@ export const NetworkListMenu = ({ onClose }) => { {t('showTestnetNetworks')} { const shouldShowTestNetworks = !value; dispatch(setShowTestNetworks(shouldShowTestNetworks)); @@ -167,7 +166,7 @@ export const NetworkListMenu = ({ onClose }) => { }} /> - {showTestNetworks ? ( + {showTestNetworks || currentlyOnTestNetwork ? ( {generateMenuItems(testNetworks)} diff --git a/ui/components/multichain/network-list-menu/network-list-menu.test.js b/ui/components/multichain/network-list-menu/network-list-menu.test.js index cd6dae498..6608b1bae 100644 --- a/ui/components/multichain/network-list-menu/network-list-menu.test.js +++ b/ui/components/multichain/network-list-menu/network-list-menu.test.js @@ -4,6 +4,7 @@ import { fireEvent, renderWithProvider } from '../../../../test/jest'; import configureStore from '../../../store/store'; import mockState from '../../../../test/data/mock-state.json'; import { + CHAIN_IDS, MAINNET_DISPLAY_NAME, SEPOLIA_DISPLAY_NAME, } from '../../../../shared/constants/network'; @@ -18,10 +19,14 @@ jest.mock('../../../store/actions.ts', () => ({ toggleNetworkMenu: () => mockToggleNetworkMenu, })); -const render = (showTestNetworks = false) => { +const render = (showTestNetworks = false, currentChainId = '0x1') => { const store = configureStore({ metamask: { ...mockState.metamask, + providerConfig: { + ...mockState.metamask.providerConfig, + chainId: currentChainId, + }, preferences: { showTestNetworks, }, @@ -55,6 +60,11 @@ describe('NetworkListMenu', () => { expect(mockSetShowTestNetworks).toHaveBeenCalled(); }); + it('disables toggle when on test network', () => { + const { container } = render(false, CHAIN_IDS.GOERLI); + expect(container.querySelector('.toggle-button--disabled')).toBeDefined(); + }); + it('switches networks when an item is clicked', () => { const { getByText } = render(); fireEvent.click(getByText(MAINNET_DISPLAY_NAME)); From 7bdd76a4ad6cbb9a75515eca50ffcd1285b36324 Mon Sep 17 00:00:00 2001 From: Nidhi Kumari Date: Fri, 14 Jul 2023 21:12:01 +0530 Subject: [PATCH 049/172] updated hardware wallet text (#20026) --- app/_locales/en/messages.json | 6 +++--- test/e2e/tests/import-flow.spec.js | 2 +- .../multichain/account-list-menu/account-list-menu.js | 2 +- .../multichain/account-list-menu/account-list-menu.test.js | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index fd9c12b64..d801f3383 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -249,6 +249,9 @@ "addFromAListOfPopularNetworks": { "message": "Add from a list of popular networks or add a network manually. Only interact with the entities you trust." }, + "addHardwareWallet": { + "message": "Add hardware wallet" + }, "addMemo": { "message": "Add memo" }, @@ -1758,9 +1761,6 @@ "hardware": { "message": "Hardware" }, - "hardwareWallet": { - "message": "Hardware wallet" - }, "hardwareWalletConnected": { "message": "Hardware wallet connected" }, diff --git a/test/e2e/tests/import-flow.spec.js b/test/e2e/tests/import-flow.spec.js index b89e2bbf5..8003822b2 100644 --- a/test/e2e/tests/import-flow.spec.js +++ b/test/e2e/tests/import-flow.spec.js @@ -374,7 +374,7 @@ describe('Import flow', function () { // choose Connect hardware wallet from the account menu await driver.clickElement('[data-testid="account-menu-icon"]'); await driver.clickElement({ - text: 'Hardware wallet', + text: 'Add hardware wallet', tag: 'button', }); await driver.delay(regularDelayMs); diff --git a/ui/components/multichain/account-list-menu/account-list-menu.js b/ui/components/multichain/account-list-menu/account-list-menu.js index 4e942d823..52f17dba6 100644 --- a/ui/components/multichain/account-list-menu/account-list-menu.js +++ b/ui/components/multichain/account-list-menu/account-list-menu.js @@ -260,7 +260,7 @@ export const AccountListMenu = ({ onClose }) => { } }} > - {t('hardwareWallet')} + {t('addHardwareWallet')} { diff --git a/ui/components/multichain/account-list-menu/account-list-menu.test.js b/ui/components/multichain/account-list-menu/account-list-menu.test.js index b1c789b2f..60b9ef243 100644 --- a/ui/components/multichain/account-list-menu/account-list-menu.test.js +++ b/ui/components/multichain/account-list-menu/account-list-menu.test.js @@ -62,7 +62,7 @@ describe('AccountListMenu', () => { expect(getByPlaceholderText('Search accounts')).toBeInTheDocument(); expect(getByText('Add account')).toBeInTheDocument(); expect(getByText('Import account')).toBeInTheDocument(); - expect(getByText('Hardware wallet')).toBeInTheDocument(); + expect(getByText('Add hardware wallet')).toBeInTheDocument(); }); it('shows the account creation UI when Add Account is clicked', () => { @@ -87,7 +87,7 @@ describe('AccountListMenu', () => { it('navigates to hardware wallet connection screen when clicked', () => { const { getByText } = render(); - fireEvent.click(getByText('Hardware wallet')); + fireEvent.click(getByText('Add hardware wallet')); expect(historyPushMock).toHaveBeenCalledWith(CONNECT_HARDWARE_ROUTE); }); From 5bc0ba7f3a7495ed29f3149300a0c1d907634e0e Mon Sep 17 00:00:00 2001 From: Nidhi Kumari Date: Fri, 14 Jul 2023 21:48:41 +0530 Subject: [PATCH 050/172] Move "Import NFTs" to Modal (#19806) * moved import nft to modal * fixed modal state * updated port-nft-popup * updated onChange for import nft modal * updated tests * updated tests * updated tests * added story and updated spec file * updated spec file * updated spec file * updated spec file for import-nft * added focus to form field * added autofocus to tokenId --- .../files-to-convert.json | 3 - test/e2e/nft/import-erc1155.spec.js | 19 +- test/e2e/nft/import-nft.spec.js | 18 +- .../convert-token-to-nft-modal.js | 12 +- .../app/nfts-detection-notice/index.scss | 2 - ui/components/app/nfts-tab/nfts-tab.js | 19 +- ui/components/app/nfts-tab/nfts-tab.test.js | 14 +- .../import-nfts-modal/import-nfts-modal.js | 286 ++++++++++++++++++ .../import-nfts-modal.stories.js | 38 +++ .../import-nfts-modal.test.js} | 97 +++--- .../multichain/import-nfts-modal/index.js | 1 + .../multichain/import-nfts-modal}/index.scss | 0 ui/components/multichain/index.js | 1 + .../multichain/multichain-components.scss | 1 + ui/ducks/app/app.ts | 13 + ui/helpers/constants/routes.ts | 2 - ui/pages/add-nft/add-nft.js | 206 ------------- ui/pages/add-nft/index.js | 1 - ui/pages/home/home.component.js | 7 +- .../import-token/import-token.component.js | 18 +- .../import-token/import-token.container.js | 2 + ui/pages/pages.scss | 1 - ui/pages/routes/routes.component.js | 11 +- ui/pages/routes/routes.container.js | 3 + ui/store/actionConstants.ts | 2 + ui/store/actions.ts | 12 + 26 files changed, 473 insertions(+), 316 deletions(-) create mode 100644 ui/components/multichain/import-nfts-modal/import-nfts-modal.js create mode 100644 ui/components/multichain/import-nfts-modal/import-nfts-modal.stories.js rename ui/{pages/add-nft/add-nft.test.js => components/multichain/import-nfts-modal/import-nfts-modal.test.js} (56%) create mode 100644 ui/components/multichain/import-nfts-modal/index.js rename ui/{pages/add-nft => components/multichain/import-nfts-modal}/index.scss (100%) delete mode 100644 ui/pages/add-nft/add-nft.js delete mode 100644 ui/pages/add-nft/index.js diff --git a/development/ts-migration-dashboard/files-to-convert.json b/development/ts-migration-dashboard/files-to-convert.json index 08d1a48e1..0ba074760 100644 --- a/development/ts-migration-dashboard/files-to-convert.json +++ b/development/ts-migration-dashboard/files-to-convert.json @@ -1162,9 +1162,6 @@ "ui/hooks/useUserPreferencedCurrency.test.js", "ui/index.js", "ui/index.test.js", - "ui/pages/add-nft/add-nft.js", - "ui/pages/add-nft/add-nft.test.js", - "ui/pages/add-nft/index.js", "ui/pages/asset/asset.js", "ui/pages/asset/components/asset-breadcrumb.js", "ui/pages/asset/components/asset-navigation.js", diff --git a/test/e2e/nft/import-erc1155.spec.js b/test/e2e/nft/import-erc1155.spec.js index e27155e3c..516b82aba 100644 --- a/test/e2e/nft/import-erc1155.spec.js +++ b/test/e2e/nft/import-erc1155.spec.js @@ -38,9 +38,11 @@ describe('Import ERC1155 NFT', function () { await driver.clickElement({ text: 'Import NFT', tag: 'button' }); // Enter a valid NFT that belongs to user and check success message appears - await driver.fill('[data-testid="address"]', contractAddress); - await driver.fill('[data-testid="token-id"]', '1'); - await driver.clickElement({ text: 'Add', tag: 'button' }); + await driver.fill('#address', contractAddress); + await driver.fill('#token-id', '1'); + await driver.clickElement( + '[data-testid="import-nfts-modal-import-button"]', + ); const newNftNotification = await driver.findVisibleElement({ text: 'NFT was successfully added!', @@ -86,14 +88,15 @@ describe('Import ERC1155 NFT', function () { await driver.clickElement({ text: 'Import NFT', tag: 'button' }); // Enter an NFT that not belongs to user with a valid address and an invalid token id - await driver.fill('[data-testid="address"]', contractAddress); - await driver.fill('[data-testid="token-id"]', '4'); - await driver.clickElement({ text: 'Add', tag: 'button' }); - + await driver.fill('#address', contractAddress); + await driver.fill('#token-id', '4'); + await driver.clickElement( + '[data-testid="import-nfts-modal-import-button"]', + ); // Check error message appears const invalidNftNotification = await driver.findElement({ text: 'NFT can’t be added as the ownership details do not match. Make sure you have entered correct information.', - tag: 'h6', + tag: 'p', }); assert.equal(await invalidNftNotification.isDisplayed(), true); }, diff --git a/test/e2e/nft/import-nft.spec.js b/test/e2e/nft/import-nft.spec.js index 373edc70a..c0fc22876 100644 --- a/test/e2e/nft/import-nft.spec.js +++ b/test/e2e/nft/import-nft.spec.js @@ -38,9 +38,11 @@ describe('Import NFT', function () { await driver.clickElement({ text: 'Import NFT', tag: 'button' }); // Enter a valid NFT that belongs to user and check success message appears - await driver.fill('[data-testid="address"]', contractAddress); - await driver.fill('[data-testid="token-id"]', '1'); - await driver.clickElement({ text: 'Add', tag: 'button' }); + await driver.fill('#address', contractAddress); + await driver.fill('#token-id', '1'); + await driver.clickElement( + '[data-testid="import-nfts-modal-import-button"]', + ); const newNftNotification = await driver.findElement({ text: 'NFT was successfully added!', @@ -85,14 +87,16 @@ describe('Import NFT', function () { await driver.clickElement({ text: 'Import NFT', tag: 'button' }); // Enter an NFT that not belongs to user with a valid address and an invalid token id - await driver.fill('[data-testid="address"]', contractAddress); - await driver.fill('[data-testid="token-id"]', '2'); - await driver.clickElement({ text: 'Add', tag: 'button' }); + await driver.fill('#address', contractAddress); + await driver.fill('#token-id', '2'); + await driver.clickElement( + '[data-testid="import-nfts-modal-import-button"]', + ); // Check error message appears const invalidNftNotification = await driver.findElement({ text: 'NFT can’t be added as the ownership details do not match. Make sure you have entered correct information.', - tag: 'h6', + tag: 'p', }); assert.equal(await invalidNftNotification.isDisplayed(), true); }, diff --git a/ui/components/app/modals/convert-token-to-nft-modal/convert-token-to-nft-modal.js b/ui/components/app/modals/convert-token-to-nft-modal/convert-token-to-nft-modal.js index c818c80f1..9311153fc 100644 --- a/ui/components/app/modals/convert-token-to-nft-modal/convert-token-to-nft-modal.js +++ b/ui/components/app/modals/convert-token-to-nft-modal/convert-token-to-nft-modal.js @@ -7,12 +7,9 @@ import Typography from '../../../ui/typography'; import { TypographyVariant } from '../../../../helpers/constants/design-system'; import withModalProps from '../../../../helpers/higher-order-components/with-modal-props'; import { useI18nContext } from '../../../../hooks/useI18nContext'; -import { - ADD_NFT_ROUTE, - ASSET_ROUTE, -} from '../../../../helpers/constants/routes'; +import { ASSET_ROUTE } from '../../../../helpers/constants/routes'; import { getNfts } from '../../../../ducks/metamask/metamask'; -import { ignoreTokens } from '../../../../store/actions'; +import { ignoreTokens, showImportNftsModal } from '../../../../store/actions'; import { isEqualCaseInsensitive } from '../../../../../shared/modules/string-utils'; const ConvertTokenToNFTModal = ({ hideModal, tokenAddress }) => { @@ -39,10 +36,7 @@ const ConvertTokenToNFTModal = ({ hideModal, tokenAddress }) => { pathname: `${ASSET_ROUTE}/${tokenAddress}/${tokenId}`, }); } else { - history.push({ - pathname: ADD_NFT_ROUTE, - state: { tokenAddress }, - }); + dispatch(showImportNftsModal()); } hideModal(); }} diff --git a/ui/components/app/nfts-detection-notice/index.scss b/ui/components/app/nfts-detection-notice/index.scss index 95d13a24c..5c792262e 100644 --- a/ui/components/app/nfts-detection-notice/index.scss +++ b/ui/components/app/nfts-detection-notice/index.scss @@ -1,6 +1,4 @@ .nfts-detection-notice { - margin: 16px 16px 0 16px; - &__message { position: relative; padding: 0.75rem 0.75rem 1rem 0.75rem !important; diff --git a/ui/components/app/nfts-tab/nfts-tab.js b/ui/components/app/nfts-tab/nfts-tab.js index 69f9b3e11..2e1918c0d 100644 --- a/ui/components/app/nfts-tab/nfts-tab.js +++ b/ui/components/app/nfts-tab/nfts-tab.js @@ -1,5 +1,4 @@ import React from 'react'; -import PropTypes from 'prop-types'; import { useDispatch, useSelector } from 'react-redux'; import { useHistory } from 'react-router-dom'; import NftsItems from '../nfts-items'; @@ -19,13 +18,14 @@ import { EXPERIMENTAL_ROUTE } from '../../../helpers/constants/routes'; import { checkAndUpdateAllNftsOwnershipStatus, detectNfts, + showImportNftsModal, } from '../../../store/actions'; import { useNftsCollections } from '../../../hooks/useNftsCollections'; import { Box, ButtonLink, IconName, Text } from '../../component-library'; import NftsDetectionNotice from '../nfts-detection-notice'; import ZENDESK_URLS from '../../../helpers/constants/zendesk-url'; -export default function NftsTab({ onAddNFT }) { +export default function NftsTab() { const useNftDetection = useSelector(getUseNftDetection); const isMainnet = useSelector(getIsMainnet); const history = useHistory(); @@ -60,7 +60,11 @@ export default function NftsTab({ onAddNFT }) { /> ) : ( <> - {isMainnet && !useNftDetection ? : null}{' '} + {isMainnet && !useNftDetection ? ( + + + + ) : null} @@ -113,7 +116,9 @@ export default function NftsTab({ onAddNFT }) { size={Size.MD} data-testid="import-nft-button" startIconName={IconName.Add} - onClick={onAddNFT} + onClick={() => { + dispatch(showImportNftsModal()); + }} > {t('importNFT')} @@ -149,7 +154,3 @@ export default function NftsTab({ onAddNFT }) { ); } - -NftsTab.propTypes = { - onAddNFT: PropTypes.func.isRequired, -}; diff --git a/ui/components/app/nfts-tab/nfts-tab.test.js b/ui/components/app/nfts-tab/nfts-tab.test.js index 2cc2048d1..1bdd19e8a 100644 --- a/ui/components/app/nfts-tab/nfts-tab.test.js +++ b/ui/components/app/nfts-tab/nfts-tab.test.js @@ -150,7 +150,6 @@ const render = ({ selectedAddress, chainId = '0x1', useNftDetection, - onAddNFT = jest.fn(), }) => { const store = configureStore({ metamask: { @@ -170,7 +169,7 @@ const render = ({ nftsDropdownState, }, }); - return renderWithProvider(, store); + return renderWithProvider(, store); }; describe('NFT Items', () => { @@ -295,16 +294,5 @@ describe('NFT Items', () => { expect(historyPushMock).toHaveBeenCalledTimes(1); expect(historyPushMock).toHaveBeenCalledWith(EXPERIMENTAL_ROUTE); }); - it('should render a link "Import NFTs" when some NFTs are present, which, when clicked calls the passed in onAddNFT method', () => { - const onAddNFTStub = jest.fn(); - render({ - selectedAddress: ACCOUNT_1, - nfts: NFTS, - onAddNFT: onAddNFTStub, - }); - expect(onAddNFTStub).toHaveBeenCalledTimes(0); - fireEvent.click(screen.queryByText('Import NFT')); - expect(onAddNFTStub).toHaveBeenCalledTimes(1); - }); }); }); diff --git a/ui/components/multichain/import-nfts-modal/import-nfts-modal.js b/ui/components/multichain/import-nfts-modal/import-nfts-modal.js new file mode 100644 index 000000000..20e14d83f --- /dev/null +++ b/ui/components/multichain/import-nfts-modal/import-nfts-modal.js @@ -0,0 +1,286 @@ +import React, { useContext, useState } from 'react'; +import { useHistory } from 'react-router-dom'; +import { useDispatch, useSelector } from 'react-redux'; +import { isValidHexAddress } from '@metamask/controller-utils'; +import PropTypes from 'prop-types'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { DEFAULT_ROUTE } from '../../../helpers/constants/routes'; +import { + AlignItems, + Display, + FlexDirection, + IconColor, + JustifyContent, + Severity, + Size, +} from '../../../helpers/constants/design-system'; + +import { + addNftVerifyOwnership, + getTokenStandardAndDetails, + ignoreTokens, + setNewNftAddedMessage, + updateNftDropDownState, +} from '../../../store/actions'; +import { + getCurrentChainId, + getIsMainnet, + getSelectedAddress, + getUseNftDetection, +} from '../../../selectors'; +import { getNftsDropdownState } from '../../../ducks/metamask/metamask'; +import NftsDetectionNotice from '../../app/nfts-detection-notice'; +import { MetaMetricsContext } from '../../../contexts/metametrics'; +import { AssetType } from '../../../../shared/constants/transaction'; +import { + MetaMetricsEventName, + MetaMetricsTokenEventSource, +} from '../../../../shared/constants/metametrics'; +import { + IconName, + ModalContent, + ModalOverlay, + ModalHeader, + Modal, + ButtonPrimary, + ButtonSecondary, + Box, + FormTextField, + Label, + Icon, + IconSize, + BannerAlert, +} from '../../component-library'; +import Tooltip from '../../ui/tooltip'; + +export const ImportNftsModal = ({ onClose }) => { + const t = useI18nContext(); + const history = useHistory(); + const dispatch = useDispatch(); + const useNftDetection = useSelector(getUseNftDetection); + const isMainnet = useSelector(getIsMainnet); + const nftsDropdownState = useSelector(getNftsDropdownState); + const selectedAddress = useSelector(getSelectedAddress); + const chainId = useSelector(getCurrentChainId); + const addressEnteredOnImportTokensPage = + history?.location?.state?.addressEnteredOnImportTokensPage; + const contractAddressToConvertFromTokenToNft = + history?.location?.state?.tokenAddress; + + const [nftAddress, setNftAddress] = useState( + addressEnteredOnImportTokensPage ?? + contractAddressToConvertFromTokenToNft ?? + '', + ); + const [tokenId, setTokenId] = useState(''); + const [disabled, setDisabled] = useState(true); + const [nftAddFailed, setNftAddFailed] = useState(false); + const trackEvent = useContext(MetaMetricsContext); + + const handleAddNft = async () => { + try { + await dispatch(addNftVerifyOwnership(nftAddress, tokenId)); + const newNftDropdownState = { + ...nftsDropdownState, + [selectedAddress]: { + ...nftsDropdownState?.[selectedAddress], + [chainId]: { + ...nftsDropdownState?.[selectedAddress]?.[chainId], + [nftAddress]: true, + }, + }, + }; + + dispatch(updateNftDropDownState(newNftDropdownState)); + } catch (error) { + const { message } = error; + dispatch(setNewNftAddedMessage(message)); + setNftAddFailed(true); + return; + } + if (contractAddressToConvertFromTokenToNft) { + await dispatch( + ignoreTokens({ + tokensToIgnore: contractAddressToConvertFromTokenToNft, + dontShowLoadingIndicator: true, + }), + ); + } + dispatch(setNewNftAddedMessage('success')); + + const tokenDetails = await getTokenStandardAndDetails( + nftAddress, + null, + tokenId.toString(), + ); + + trackEvent({ + event: MetaMetricsEventName.TokenAdded, + category: 'Wallet', + sensitiveProperties: { + token_contract_address: nftAddress, + token_symbol: tokenDetails?.symbol, + tokenId: tokenId.toString(), + asset_type: AssetType.NFT, + token_standard: tokenDetails?.standard, + source_connection_method: MetaMetricsTokenEventSource.Custom, + }, + }); + + history.push(DEFAULT_ROUTE); + onClose(); + }; + + const validateAndSetAddress = (val) => { + setDisabled(!isValidHexAddress(val) || !tokenId); + setNftAddress(val); + }; + + const validateAndSetTokenId = (val) => { + setDisabled(!isValidHexAddress(nftAddress) || !val || isNaN(Number(val))); + setTokenId(val); + }; + + return ( + { + onClose(); + }} + className="import-nfts-modal" + > + + + { + onClose(); + }} + > + {t('importNFT')} + + + {isMainnet && !useNftDetection ? ( + + + + ) : null} + {nftAddFailed && ( + + setNftAddFailed(false)} + closeButtonProps={{ 'data-testid': 'add-nft-error-close' }} + > + {t('nftAddFailedMessage')} + + + )} + + + + + + + + + + + { + validateAndSetAddress(e.target.value); + setNftAddFailed(false); + }} + /> + + + + + + + + + + + { + validateAndSetTokenId(e.target.value); + setNftAddFailed(false); + }} + /> + + + + + onClose()} + block + className="import-nfts-modal__cancel-button" + > + {t('cancel')} + + handleAddNft()} + disabled={disabled} + block + data-testid="import-nfts-modal-import-button" + > + {t('import')} + + + + + ); +}; + +ImportNftsModal.propTypes = { + onClose: PropTypes.func.isRequired, +}; diff --git a/ui/components/multichain/import-nfts-modal/import-nfts-modal.stories.js b/ui/components/multichain/import-nfts-modal/import-nfts-modal.stories.js new file mode 100644 index 000000000..f6e6139ae --- /dev/null +++ b/ui/components/multichain/import-nfts-modal/import-nfts-modal.stories.js @@ -0,0 +1,38 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import configureStore from '../../../store/store'; +import testData from '../../../../.storybook/test-data'; +import { CHAIN_IDS } from '../../../../shared/constants/network'; +import { ImportNftsModal } from '.'; + +const createStore = (chainId = CHAIN_IDS.MAINNET, useTokenDetection = true) => { + return configureStore({ + ...testData, + metamask: { + ...testData.metamask, + useTokenDetection, + providerConfig: { chainId }, + }, + }); +}; + +export default { + title: 'Components/Multichain/ImportNftsModal', + component: ImportNftsModal, + argTypes: { + onClose: { + action: 'onClose', + }, + }, +}; + +export const DefaultStory = (args) => ; +DefaultStory.decorators = [ + (Story) => ( + + + + ), +]; + +DefaultStory.storyName = 'Default'; diff --git a/ui/pages/add-nft/add-nft.test.js b/ui/components/multichain/import-nfts-modal/import-nfts-modal.test.js similarity index 56% rename from ui/pages/add-nft/add-nft.test.js rename to ui/components/multichain/import-nfts-modal/import-nfts-modal.test.js index cb76d1a16..e251fc7d7 100644 --- a/ui/pages/add-nft/add-nft.test.js +++ b/ui/components/multichain/import-nfts-modal/import-nfts-modal.test.js @@ -3,16 +3,16 @@ import { fireEvent, waitFor } from '@testing-library/react'; import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import { useHistory } from 'react-router-dom'; -import { renderWithProvider } from '../../../test/jest/rendering'; -import mockState from '../../../test/data/mock-state.json'; -import { DEFAULT_ROUTE } from '../../helpers/constants/routes'; +import { renderWithProvider } from '../../../../test/jest/rendering'; +import mockState from '../../../../test/data/mock-state.json'; +import { DEFAULT_ROUTE } from '../../../helpers/constants/routes'; import { addNftVerifyOwnership, ignoreTokens, setNewNftAddedMessage, updateNftDropDownState, -} from '../../store/actions'; -import AddNft from '.'; +} from '../../../store/actions'; +import { ImportNftsModal } from '.'; const VALID_ADDRESS = '0x312BE6a98441F9F6e3F6246B13CA19701e0AC3B9'; const INVALID_ADDRESS = 'aoinsafasdfa'; @@ -33,7 +33,7 @@ jest.mock('react-router-dom', () => ({ ), })); -jest.mock('../../store/actions.ts', () => ({ +jest.mock('../../../store/actions.ts', () => ({ addNftVerifyOwnership: jest .fn() .mockReturnValue(jest.fn().mockResolvedValue()), @@ -47,56 +47,72 @@ jest.mock('../../store/actions.ts', () => ({ .mockReturnValue(jest.fn().mockResolvedValue()), })); -describe('AddNft', () => { +describe('ImportNftsModal', () => { const store = configureMockStore([thunk])(mockState); beforeEach(() => { jest.restoreAllMocks(); }); - it('should enable the "Add" button when valid entries are input into both Address and TokenId fields', () => { - const { getByTestId, getByText } = renderWithProvider(, store); - expect(getByText('Add')).not.toBeEnabled(); - fireEvent.change(getByTestId('address'), { + it('should enable the "Import" button when valid entries are input into both Address and TokenId fields', () => { + const { getByText, getByPlaceholderText } = renderWithProvider( + , + store, + ); + expect(getByText('Import')).not.toBeEnabled(); + const addressInput = getByPlaceholderText('0x...'); + const tokenIdInput = getByPlaceholderText('Enter the token id'); + fireEvent.change(addressInput, { target: { value: VALID_ADDRESS }, }); - fireEvent.change(getByTestId('token-id'), { + fireEvent.change(tokenIdInput, { target: { value: VALID_TOKENID }, }); - expect(getByText('Add')).toBeEnabled(); + expect(getByText('Import')).toBeEnabled(); }); - it('should not enable the "Add" button when an invalid entry is input into one or both Address and TokenId fields', () => { - const { getByTestId, getByText } = renderWithProvider(, store); - expect(getByText('Add')).not.toBeEnabled(); - fireEvent.change(getByTestId('address'), { + it('should not enable the "Import" button when an invalid entry is input into one or both Address and TokenId fields', () => { + const { getByText, getByPlaceholderText } = renderWithProvider( + , + store, + ); + expect(getByText('Import')).not.toBeEnabled(); + const addressInput = getByPlaceholderText('0x...'); + const tokenIdInput = getByPlaceholderText('Enter the token id'); + fireEvent.change(addressInput, { target: { value: INVALID_ADDRESS }, }); - fireEvent.change(getByTestId('token-id'), { + fireEvent.change(tokenIdInput, { target: { value: VALID_TOKENID }, }); - expect(getByText('Add')).not.toBeEnabled(); - fireEvent.change(getByTestId('address'), { + expect(getByText('Import')).not.toBeEnabled(); + fireEvent.change(addressInput, { target: { value: VALID_ADDRESS }, }); - expect(getByText('Add')).toBeEnabled(); - fireEvent.change(getByTestId('token-id'), { + expect(getByText('Import')).toBeEnabled(); + fireEvent.change(tokenIdInput, { target: { value: INVALID_TOKENID }, }); - expect(getByText('Add')).not.toBeEnabled(); + expect(getByText('Import')).not.toBeEnabled(); }); it('should call addNftVerifyOwnership, updateNftDropDownState, setNewNftAddedMessage, and ignoreTokens action with correct values (tokenId should not be in scientific notation)', async () => { - const { getByTestId, getByText } = renderWithProvider(, store); - fireEvent.change(getByTestId('address'), { + const onClose = jest.fn(); + const { getByPlaceholderText, getByText } = renderWithProvider( + , + store, + ); + const addressInput = getByPlaceholderText('0x...'); + const tokenIdInput = getByPlaceholderText('Enter the token id'); + fireEvent.change(addressInput, { target: { value: VALID_ADDRESS }, }); const LARGE_TOKEN_ID = Number.MAX_SAFE_INTEGER + 1; - fireEvent.change(getByTestId('token-id'), { + fireEvent.change(tokenIdInput, { target: { value: LARGE_TOKEN_ID }, }); - fireEvent.click(getByText('Add')); + fireEvent.click(getByText('Import')); await waitFor(() => { expect(addNftVerifyOwnership).toHaveBeenCalledWith( @@ -127,16 +143,21 @@ describe('AddNft', () => { jest.fn().mockRejectedValue(new Error('error')), ); - const { getByTestId, getByText } = renderWithProvider(, store); - fireEvent.change(getByTestId('address'), { + const { getByTestId, getByText, getByPlaceholderText } = renderWithProvider( + , + store, + ); + const addressInput = getByPlaceholderText('0x...'); + const tokenIdInput = getByPlaceholderText('Enter the token id'); + fireEvent.change(addressInput, { target: { value: VALID_ADDRESS }, }); const LARGE_TOKEN_ID = Number.MAX_SAFE_INTEGER + 1; - fireEvent.change(getByTestId('token-id'), { + fireEvent.change(tokenIdInput, { target: { value: LARGE_TOKEN_ID }, }); - fireEvent.click(getByText('Add')); + fireEvent.click(getByText('Import')); await waitFor(() => { expect(setNewNftAddedMessage).toHaveBeenCalledWith('error'); @@ -148,19 +169,23 @@ describe('AddNft', () => { }); it('should route to default route when cancel button is clicked', () => { - const { queryByTestId } = renderWithProvider(, store); + const onClose = jest.fn(); + const { getByText } = renderWithProvider( + , + store, + ); - const cancelButton = queryByTestId('page-container-footer-cancel'); + const cancelButton = getByText('Cancel'); fireEvent.click(cancelButton); expect(useHistory().push).toHaveBeenCalledWith(DEFAULT_ROUTE); }); it('should route to default route when close button is clicked', () => { - const { queryByLabelText } = renderWithProvider(, store); + const onClose = jest.fn(); + renderWithProvider(, store); - const closeButton = queryByLabelText('close'); - fireEvent.click(closeButton); + fireEvent.click(document.querySelector('button[aria-label="Close"]')); expect(useHistory().push).toHaveBeenCalledWith(DEFAULT_ROUTE); }); diff --git a/ui/components/multichain/import-nfts-modal/index.js b/ui/components/multichain/import-nfts-modal/index.js new file mode 100644 index 000000000..659f65ac0 --- /dev/null +++ b/ui/components/multichain/import-nfts-modal/index.js @@ -0,0 +1 @@ +export { ImportNftsModal } from './import-nfts-modal'; diff --git a/ui/pages/add-nft/index.scss b/ui/components/multichain/import-nfts-modal/index.scss similarity index 100% rename from ui/pages/add-nft/index.scss rename to ui/components/multichain/import-nfts-modal/index.scss diff --git a/ui/components/multichain/index.js b/ui/components/multichain/index.js index fa535a66e..0f6edcf25 100644 --- a/ui/components/multichain/index.js +++ b/ui/components/multichain/index.js @@ -15,3 +15,4 @@ export { ProductTour } from './product-tour-popover'; export { AccountDetails } from './account-details'; export { CreateAccount } from './create-account'; export { ImportAccount } from './import-account'; +export { ImportNftsModal } from './import-nfts-modal'; diff --git a/ui/components/multichain/multichain-components.scss b/ui/components/multichain/multichain-components.scss index a93926b22..00cea05fa 100644 --- a/ui/components/multichain/multichain-components.scss +++ b/ui/components/multichain/multichain-components.scss @@ -5,6 +5,7 @@ * unintended overrides. **/ @import 'address-copy-button/index'; +@import 'import-nfts-modal/index'; @import 'account-list-item/index'; @import 'account-list-item-menu/index'; @import 'account-list-menu/index'; diff --git a/ui/ducks/app/app.ts b/ui/ducks/app/app.ts index e6ea054db..e2b3a151e 100644 --- a/ui/ducks/app/app.ts +++ b/ui/ducks/app/app.ts @@ -26,6 +26,7 @@ interface AppState { values?: { address?: string | null }; } | null; networkDropdownOpen: boolean; + importNftsModalOpen: boolean; accountDetail: { subview?: string; accountExport?: string; @@ -94,6 +95,7 @@ const initialState: AppState = { alertMessage: null, qrCodeData: null, networkDropdownOpen: false, + importNftsModalOpen: false, accountDetail: { privateKey: '', }, @@ -163,6 +165,17 @@ export default function reduceApp( networkDropdownOpen: false, }; + case actionConstants.IMPORT_NFTS_MODAL_OPEN: + return { + ...appState, + importNftsModalOpen: true, + }; + + case actionConstants.IMPORT_NFTS_MODAL_CLOSE: + return { + ...appState, + importNftsModalOpen: false, + }; // alert methods case actionConstants.ALERT_OPEN: return { diff --git a/ui/helpers/constants/routes.ts b/ui/helpers/constants/routes.ts index 3e2e4e1b1..53b864cb8 100644 --- a/ui/helpers/constants/routes.ts +++ b/ui/helpers/constants/routes.ts @@ -66,7 +66,6 @@ const SMART_TRANSACTION_STATUS_ROUTE = '/swaps/smart-transaction-status'; const AWAITING_SWAP_ROUTE = '/swaps/awaiting-swap'; const SWAPS_ERROR_ROUTE = '/swaps/swaps-error'; const SWAPS_MAINTENANCE_ROUTE = '/swaps/maintenance'; -const ADD_NFT_ROUTE = '/add-nft'; const ONBOARDING_ROUTE = '/onboarding'; const ONBOARDING_REVIEW_SRP_ROUTE = '/onboarding/review-recovery-phrase'; @@ -273,7 +272,6 @@ export { SWAPS_ERROR_ROUTE, SWAPS_MAINTENANCE_ROUTE, SMART_TRANSACTION_STATUS_ROUTE, - ADD_NFT_ROUTE, ONBOARDING_ROUTE, ONBOARDING_HELP_US_IMPROVE_ROUTE, ONBOARDING_CREATE_PASSWORD_ROUTE, diff --git a/ui/pages/add-nft/add-nft.js b/ui/pages/add-nft/add-nft.js deleted file mode 100644 index 9772c9c25..000000000 --- a/ui/pages/add-nft/add-nft.js +++ /dev/null @@ -1,206 +0,0 @@ -import React, { useContext, useState } from 'react'; -import { useHistory } from 'react-router-dom'; -import { useDispatch, useSelector } from 'react-redux'; -import { isValidHexAddress } from '@metamask/controller-utils'; -import { useI18nContext } from '../../hooks/useI18nContext'; -import { DEFAULT_ROUTE } from '../../helpers/constants/routes'; -import { - DISPLAY, - FONT_WEIGHT, - TypographyVariant, -} from '../../helpers/constants/design-system'; - -import Box from '../../components/ui/box'; -import Typography from '../../components/ui/typography'; -import ActionableMessage from '../../components/ui/actionable-message'; -import PageContainer from '../../components/ui/page-container'; -import { - addNftVerifyOwnership, - getTokenStandardAndDetails, - ignoreTokens, - setNewNftAddedMessage, - updateNftDropDownState, -} from '../../store/actions'; -import FormField from '../../components/ui/form-field'; -import { - getCurrentChainId, - getIsMainnet, - getSelectedAddress, - getUseNftDetection, -} from '../../selectors'; -import { getNftsDropdownState } from '../../ducks/metamask/metamask'; -import NftsDetectionNotice from '../../components/app/nfts-detection-notice'; -import { MetaMetricsContext } from '../../contexts/metametrics'; -import { AssetType } from '../../../shared/constants/transaction'; -import { - MetaMetricsEventName, - MetaMetricsTokenEventSource, -} from '../../../shared/constants/metametrics'; -import { - ButtonIcon, - IconName, - ButtonIconSize, -} from '../../components/component-library'; - -export default function AddNft() { - const t = useI18nContext(); - const history = useHistory(); - const dispatch = useDispatch(); - const useNftDetection = useSelector(getUseNftDetection); - const isMainnet = useSelector(getIsMainnet); - const nftsDropdownState = useSelector(getNftsDropdownState); - const selectedAddress = useSelector(getSelectedAddress); - const chainId = useSelector(getCurrentChainId); - const addressEnteredOnImportTokensPage = - history?.location?.state?.addressEnteredOnImportTokensPage; - const contractAddressToConvertFromTokenToNft = - history?.location?.state?.tokenAddress; - - const [nftAddress, setNftAddress] = useState( - addressEnteredOnImportTokensPage ?? - contractAddressToConvertFromTokenToNft ?? - '', - ); - const [tokenId, setTokenId] = useState(''); - const [disabled, setDisabled] = useState(true); - const [nftAddFailed, setNftAddFailed] = useState(false); - const trackEvent = useContext(MetaMetricsContext); - - const handleAddNft = async () => { - try { - await dispatch(addNftVerifyOwnership(nftAddress, tokenId)); - const newNftDropdownState = { - ...nftsDropdownState, - [selectedAddress]: { - ...nftsDropdownState?.[selectedAddress], - [chainId]: { - ...nftsDropdownState?.[selectedAddress]?.[chainId], - [nftAddress]: true, - }, - }, - }; - - dispatch(updateNftDropDownState(newNftDropdownState)); - } catch (error) { - const { message } = error; - dispatch(setNewNftAddedMessage(message)); - setNftAddFailed(true); - return; - } - if (contractAddressToConvertFromTokenToNft) { - await dispatch( - ignoreTokens({ - tokensToIgnore: contractAddressToConvertFromTokenToNft, - dontShowLoadingIndicator: true, - }), - ); - } - dispatch(setNewNftAddedMessage('success')); - - const tokenDetails = await getTokenStandardAndDetails( - nftAddress, - null, - tokenId.toString(), - ); - - trackEvent({ - event: MetaMetricsEventName.TokenAdded, - category: 'Wallet', - sensitiveProperties: { - token_contract_address: nftAddress, - token_symbol: tokenDetails?.symbol, - tokenId: tokenId.toString(), - asset_type: AssetType.NFT, - token_standard: tokenDetails?.standard, - source_connection_method: MetaMetricsTokenEventSource.Custom, - }, - }); - - history.push(DEFAULT_ROUTE); - }; - - const validateAndSetAddress = (val) => { - setDisabled(!isValidHexAddress(val) || !tokenId); - setNftAddress(val); - }; - - const validateAndSetTokenId = (val) => { - setDisabled(!isValidHexAddress(nftAddress) || !val || isNaN(Number(val))); - setTokenId(val); - }; - - return ( - { - handleAddNft(); - }} - submitText={t('add')} - onCancel={() => { - history.push(DEFAULT_ROUTE); - }} - onClose={() => { - history.push(DEFAULT_ROUTE); - }} - disabled={disabled} - contentComponent={ - - {isMainnet && !useNftDetection ? : null} - {nftAddFailed && ( - - - - {t('nftAddFailedMessage')} - - setNftAddFailed(false)} - /> - - } - /> - - )} - - { - validateAndSetAddress(val); - setNftAddFailed(false); - }} - tooltipText={t('importNFTAddressToolTip')} - autoFocus - /> - { - validateAndSetTokenId(val); - setNftAddFailed(false); - }} - tooltipText={t('importNFTTokenIdToolTip')} - /> - - - } - /> - ); -} diff --git a/ui/pages/add-nft/index.js b/ui/pages/add-nft/index.js deleted file mode 100644 index 603e8378b..000000000 --- a/ui/pages/add-nft/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './add-nft'; diff --git a/ui/pages/home/home.component.js b/ui/pages/home/home.component.js index 602ce34cd..6bd76ea55 100644 --- a/ui/pages/home/home.component.js +++ b/ui/pages/home/home.component.js @@ -62,7 +62,6 @@ import { BUILD_QUOTE_ROUTE, VIEW_QUOTE_ROUTE, CONFIRMATION_V_NEXT_ROUTE, - ADD_NFT_ROUTE, ONBOARDING_SECURE_YOUR_WALLET_ROUTE, ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) CONFIRM_INSTITUTIONAL_FEATURE_CONNECT, @@ -879,11 +878,7 @@ export default class Home extends PureComponent { name={this.context.t('nfts')} tabKey="nfts" > - { - history.push(ADD_NFT_ROUTE); - }} - /> + ///: END:ONLY_INCLUDE_IN } diff --git a/ui/pages/import-token/import-token.component.js b/ui/pages/import-token/import-token.component.js index ffda0ca12..20a00d1aa 100644 --- a/ui/pages/import-token/import-token.component.js +++ b/ui/pages/import-token/import-token.component.js @@ -8,7 +8,6 @@ import { } from '../../helpers/utils/util'; import { tokenInfoGetter } from '../../helpers/utils/token-util'; import { - ADD_NFT_ROUTE, CONFIRM_IMPORT_TOKEN_ROUTE, SECURITY_ROUTE, } from '../../helpers/constants/routes'; @@ -60,6 +59,11 @@ class ImportToken extends Component { */ clearPendingTokens: PropTypes.func, + /** + * Clear the list of pending tokens. Called when closing the modal. + */ + showImportNftsModal: PropTypes.func, + /** * The list of already added tokens. */ @@ -314,21 +318,15 @@ class ImportToken extends Component { nftAddressError: this.context.t('nftAddressError', [ - this.props.history.push({ - pathname: ADD_NFT_ROUTE, - state: { - addressEnteredOnImportTokensPage: this.state.customAddress, - }, - }) - } + onClick={() => { + this.props.showImportNftsModal(); + }} key="nftAddressError" > {this.context.t('importNFTPage')} , ]), }); - break; case isMainnetToken && !isMainnetNetwork: this.setState({ diff --git a/ui/pages/import-token/import-token.container.js b/ui/pages/import-token/import-token.container.js index 566783bc5..9d238d646 100644 --- a/ui/pages/import-token/import-token.container.js +++ b/ui/pages/import-token/import-token.container.js @@ -4,6 +4,7 @@ import { setPendingTokens, clearPendingTokens, getTokenStandardAndDetails, + showImportNftsModal, } from '../../store/actions'; import { getMostRecentOverviewPage } from '../../ducks/history/history'; import { getProviderConfig } from '../../ducks/metamask/metamask'; @@ -58,6 +59,7 @@ const mapDispatchToProps = (dispatch) => { return { setPendingTokens: (tokens) => dispatch(setPendingTokens(tokens)), clearPendingTokens: () => dispatch(clearPendingTokens()), + showImportNftsModal: () => dispatch(showImportNftsModal()), getTokenStandardAndDetails: (address, selectedAddress) => getTokenStandardAndDetails(address, selectedAddress, null), }; diff --git a/ui/pages/pages.scss b/ui/pages/pages.scss index 313f1f538..b582d5fa5 100644 --- a/ui/pages/pages.scss +++ b/ui/pages/pages.scss @@ -1,5 +1,4 @@ /** Please import your files in alphabetical order **/ -@import 'add-nft/index'; @import 'keyring-snaps/index'; @import 'import-token/index'; @import 'asset/asset'; diff --git a/ui/pages/routes/routes.component.js b/ui/pages/routes/routes.component.js index e9386e606..681f05a51 100644 --- a/ui/pages/routes/routes.component.js +++ b/ui/pages/routes/routes.component.js @@ -19,7 +19,6 @@ import PermissionsConnect from '../permissions-connect'; import RestoreVaultPage from '../keychains/restore-vault'; import RevealSeedConfirmation from '../keychains/reveal-seed'; import ImportTokenPage from '../import-token'; -import AddNftPage from '../add-nft'; import ConfirmImportTokenPage from '../confirm-import-token'; import ConfirmAddSuggestedTokenPage from '../confirm-add-suggested-token'; import CreateAccountPage from '../create-account/create-account.component'; @@ -33,6 +32,7 @@ import { AccountListMenu, NetworkListMenu, AccountDetails, + ImportNftsModal, } from '../../components/multichain'; import UnlockPage from '../unlock-page'; import Alerts from '../../components/app/alerts'; @@ -80,7 +80,6 @@ import { CONFIRMATION_V_NEXT_ROUTE, CONFIRM_IMPORT_TOKEN_ROUTE, ONBOARDING_ROUTE, - ADD_NFT_ROUTE, ONBOARDING_UNLOCK_ROUTE, TOKEN_DETAILS, ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) @@ -162,6 +161,8 @@ export default class Routes extends Component { isNetworkMenuOpen: PropTypes.bool, toggleNetworkMenu: PropTypes.func, accountDetailsAddress: PropTypes.string, + isImportNftsModalOpen: PropTypes.bool.isRequired, + hideImportNftsModal: PropTypes.func.isRequired, }; static contextTypes = { @@ -284,7 +285,6 @@ export default class Routes extends Component { component={ImportTokenPage} exact /> - ) : null} + {isImportNftsModalOpen ? ( + hideImportNftsModal()} /> + ) : null} {isLoading ? : null} {!isLoading && isNetworkLoading ? : null} diff --git a/ui/pages/routes/routes.container.js b/ui/pages/routes/routes.container.js index ba1c33777..5f31829d1 100644 --- a/ui/pages/routes/routes.container.js +++ b/ui/pages/routes/routes.container.js @@ -15,6 +15,7 @@ import { } from '../../selectors'; import { lockMetamask, + hideImportNftsModal, setCurrentCurrency, setLastActiveTime, setMouseUserState, @@ -63,6 +64,7 @@ function mapStateToProps(state) { isAccountMenuOpen: state.metamask.isAccountMenuOpen, isNetworkMenuOpen: state.metamask.isNetworkMenuOpen, accountDetailsAddress: state.appState.accountDetailsAddress, + isImportNftsModalOpen: state.appState.importNftsModalOpen, }; } @@ -77,6 +79,7 @@ function mapDispatchToProps(dispatch) { prepareToLeaveSwaps: () => dispatch(prepareToLeaveSwaps()), toggleAccountMenu: () => dispatch(toggleAccountMenu()), toggleNetworkMenu: () => dispatch(toggleNetworkMenu()), + hideImportNftsModal: () => dispatch(hideImportNftsModal()), }; } diff --git a/ui/store/actionConstants.ts b/ui/store/actionConstants.ts index 73d488a81..951b6d710 100644 --- a/ui/store/actionConstants.ts +++ b/ui/store/actionConstants.ts @@ -9,6 +9,8 @@ export const QR_CODE_DETECTED = 'UI_QR_CODE_DETECTED'; // network dropdown open export const NETWORK_DROPDOWN_OPEN = 'UI_NETWORK_DROPDOWN_OPEN'; export const NETWORK_DROPDOWN_CLOSE = 'UI_NETWORK_DROPDOWN_CLOSE'; +export const IMPORT_NFTS_MODAL_OPEN = 'UI_IMPORT_NFTS_MODAL_OPEN'; +export const IMPORT_NFTS_MODAL_CLOSE = 'UI_IMPORT_NFTS_MODAL_CLOSE'; // remote state export const UPDATE_METAMASK_STATE = 'UPDATE_METAMASK_STATE'; export const SELECTED_ADDRESS_CHANGED = 'SELECTED_ADDRESS_CHANGED'; diff --git a/ui/store/actions.ts b/ui/store/actions.ts index 8708c0fd4..46ef92d12 100644 --- a/ui/store/actions.ts +++ b/ui/store/actions.ts @@ -2402,6 +2402,18 @@ export function hideModal(): Action { }; } +export function showImportNftsModal(): Action { + return { + type: actionConstants.IMPORT_NFTS_MODAL_OPEN, + }; +} + +export function hideImportNftsModal(): Action { + return { + type: actionConstants.IMPORT_NFTS_MODAL_CLOSE, + }; +} + export function closeCurrentNotificationWindow(): ThunkAction< void, MetaMaskReduxState, From 74cc312cb1e1810f0f0b4cbc1d688efcf5329f55 Mon Sep 17 00:00:00 2001 From: George Marshall Date: Fri, 14 Jul 2023 10:59:30 -0700 Subject: [PATCH 051/172] Updating Text and import paths (#19949) --- ui/components/app/add-network/add-network.js | 2 +- .../advanced-gas-fee-defaults.js | 2 +- .../advanced-gas-fee-gas-limit.js | 2 +- .../approve-content-card.js | 2 +- ui/components/app/beta-header/index.js | 8 +- .../cancel-speedup-popover.js | 3 +- .../configure-snap-popup.tsx | 2 +- .../app/confirm-data/confirm-data.js | 2 +- .../confirm-legacy-gas-display.js | 2 +- .../app/confirm-hexdata/confirm-hexdata.js | 2 +- .../confirm-page-container.component.js | 2 +- .../snaps/snap-insight.js | 2 +- .../app/confirm-subtitle/confirm-subtitle.js | 2 +- .../app/confirm-title/confirm-title.js | 2 +- .../confirmation-warning-modal.js | 3 +- .../recipient-group.component.js | 2 +- .../app/create-new-vault/create-new-vault.js | 2 +- .../custom-spending-cap-tooltip.js | 3 +- .../custom-spending-cap.js | 3 +- .../detected-token-address.js | 2 +- .../detected-token-aggregators.js | 3 +- .../detected-token-ignored-popover.js | 2 +- .../detected-token-values.js | 3 +- .../edit-gas-display.component.js | 2 +- .../edit-gas-fee-button.js | 3 +- .../edit-gas-fee-popover.js | 2 +- .../edit-gas-tooltip/edit-gas-tooltip.js | 2 +- .../network-statistics/network-statistics.js | 2 +- .../gas-details-item-title.js | 2 +- .../ledger-instruction-field.js | 3 +- .../loading-network-screen.component.js | 2 +- .../contract-details-modal.js | 3 +- .../customize-nonce.component.js | 2 +- .../modals/eth-sign-modal/eth-sign-modal.js | 2 +- .../export-private-key-modal.component.js | 2 +- .../hold-to-reveal-modal.js | 2 +- .../network-account-balance-header.js | 2 +- .../nft-default-image/nft-default-image.js | 2 +- ui/components/app/nft-details/nft-details.js | 3 +- .../nfts-detection-notice.js | 3 +- ui/components/app/nfts-tab/nfts-tab.js | 3 +- .../permission-cell-options.js | 3 +- .../app/permission-cell/permission-cell.js | 9 +- .../qr-hardware-sign-request/player.js | 2 +- .../recovery-phrase-reminder.js | 2 +- .../security-provider-banner-message.js | 3 +- .../set-approval-for-all-warning.js | 2 +- .../signature-request-original.component.js | 3 +- .../signature-request-siwe-message.js | 2 +- .../signature-request-siwe-tag/index.js | 2 +- .../signature-request-siwe.js | 3 +- .../signature-request-message.js | 2 +- .../signature-request.component.js | 2 +- .../app/snaps/install-error/install-error.js | 3 +- .../snap-authorship-expanded.js | 3 +- .../snap-authorship-header.js | 2 +- .../snap-connect-cell/snap-connect-cell.js | 9 +- .../snaps/snap-delineator/snap-delineator.js | 8 +- .../snap-install-warning.js | 3 +- .../snap-privacy-warning.js | 2 +- .../snap-settings-card/snap-settings-card.js | 3 +- .../snap-ui-renderer/snap-ui-renderer.js | 2 +- .../app/snaps/snap-version/snap-version.js | 2 +- ui/components/app/srp-input/srp-input.js | 2 +- .../QuizContent/QuizContent.tsx | 3 +- .../terms-of-use-popup/terms-of-use-popup.js | 2 +- .../transaction-alerts/transaction-alerts.js | 3 +- ...transaction-list-item-details.component.js | 3 +- .../app/whats-new-popup/whats-new-popup.js | 2 +- .../avatar-base/avatar-base.tsx | 4 +- .../avatar-base/avatar-base.types.ts | 2 +- .../avatar-token/avatar-token.stories.js | 9 +- .../banner-base/banner-base.js | 11 +- .../button-base/button-base.js | 6 +- .../component-library/help-text/help-text.js | 2 +- .../component-library/input/input.js | 2 +- .../component-library/label/label.js | 2 +- .../modal-header/modal-header.stories.tsx | 3 +- .../modal-header/modal-header.tsx | 10 +- .../picker-network/picker-network.js | 7 +- .../popover-header/popover-header.tsx | 3 +- .../component-library/tag-url/tag-url.js | 8 +- ui/components/component-library/tag/tag.js | 4 +- .../text-field-search/text-field-search.js | 2 +- .../component-library/text/README.mdx | 35 ++-- .../text/__snapshots__/text.test.tsx.snap | 26 +-- .../{text.test.js.snap => text.test.tsx.snap} | 15 ++ .../text/deprecated/index.js | 2 - .../text/deprecated/index.ts | 3 + .../text/deprecated/text.constants.js | 11 -- .../component-library/text/deprecated/text.js | 185 ------------------ .../{text.test.js => text.test.tsx} | 43 ++-- .../text/deprecated/text.tsx | 89 +++++++++ .../text/deprecated/text.types.ts | 146 ++++++++++++++ ui/components/component-library/text/index.ts | 6 +- .../component-library/text/text.scss | 4 +- .../component-library/text/text.stories.tsx | 81 +++++--- .../component-library/text/text.test.tsx | 33 ++-- ui/components/component-library/text/text.tsx | 113 +++++------ .../component-library/text/text.types.ts | 34 ++-- .../compliance-details/compliance-details.js | 3 +- .../compliance-modal/compliance-modal.js | 3 +- .../compliance-settings.js | 8 +- .../confirm-remove-jwt-modal.js | 2 +- .../custody-confirm-link-modal.js | 3 +- .../custody-labels/custody-labels.js | 3 +- .../interactive-replacement-token-modal.js | 2 +- ...eractive-replacement-token-notification.js | 2 +- .../jwt-dropdown/jwt-dropdown.js | 3 +- .../jwt-url-form/jwt-url-form.js | 3 +- .../note-to-trader/note-to-trader.js | 3 +- .../transaction-failed.js | 3 +- .../wrong-network-notification.js | 3 +- .../account-details-authenticate.js | 2 +- .../account-details/account-details-key.js | 2 +- .../account-details/account-details.js | 2 +- .../account-list-item-menu.js | 2 +- .../account-list-item/account-list-item.js | 2 +- .../account-list-menu/account-list-menu.js | 2 +- .../account-picker/account-picker.js | 2 +- .../multichain/global-menu/global-menu.js | 10 +- .../import-account/import-account.js | 3 +- .../multichain/import-account/json.js | 2 +- .../network-list-menu/network-list-menu.js | 2 +- .../product-tour-popover.js | 9 +- .../token-list-item/token-list-item.js | 2 +- ui/components/ui/box/box.stories.tsx | 2 +- ui/components/ui/callout/callout.js | 3 +- ui/components/ui/callout/callout.stories.js | 2 +- .../deprecated-test-networks.js | 3 +- .../ui/editable-label/editable-label.js | 8 +- .../export-text-container.component.js | 3 +- ui/components/ui/form-field/form-field.js | 3 +- .../ui/form-field/form-field.stories.js | 3 +- ui/components/ui/icon-button/icon-button.js | 2 +- ui/components/ui/logo/logo.stories.js | 2 +- ui/components/ui/menu/menu-item.js | 3 +- .../ui/metafox-logo/metafox-logo.stories.js | 2 +- .../ui/new-network-info/new-network-info.js | 3 +- ui/components/ui/nft-info/nft-info.js | 2 +- .../numeric-input/numeric-input.component.js | 2 +- ui/components/ui/popover/popover.component.js | 9 +- .../ui/radio-group/radio-group.component.js | 2 +- .../review-spending-cap.js | 9 +- ui/components/ui/slider/slider.component.js | 2 +- .../tabs/snaps/dropdown-tab/dropdown-tab.js | 3 +- ui/components/ui/tooltip/tooltip.stories.js | 1 - ui/helpers/utils/accounts.js | 4 +- ui/helpers/utils/permission.js | 2 +- .../confirm-add-suggested-nft.js | 2 +- ...irm-approve-content.component.test.js.snap | 16 +- .../confirm-approve-content.component.js | 2 +- .../confirm-deploy-contract.component.js | 2 +- .../create-account/connect-hardware/index.js | 2 +- .../desktop-pairing.component.js | 3 +- ui/pages/home/home.component.js | 2 +- .../compliance-feature-page.js | 2 +- .../confirm-add-custodian-token.js | 2 +- .../confirm-add-institutional-feature.js | 2 +- .../connect-custody/account-list.js | 2 +- ui/pages/institutional/custody/custody.js | 2 +- .../institutional-entity-done-page.js | 2 +- .../interactive-replacement-token-page.js | 2 +- ui/pages/keychains/reveal-seed.js | 2 +- .../add-snap-account-modal.tsx | 2 +- .../new-snap-account-page.tsx | 3 +- .../snap-account-detail-page/detail.tsx | 3 +- .../snap-account-detail-page/header.tsx | 2 +- .../snap-account-detail-page.tsx | 2 +- .../keyring-snaps/snap-card/snap-card.tsx | 6 +- .../pin-extension/pin-extension.js | 2 +- .../secure-your-wallet/secure-your-wallet.js | 2 +- ui/pages/onboarding-flow/welcome/welcome.js | 2 +- .../snaps/snap-install/snap-install.js | 2 +- .../snaps/snap-result/snap-result.js | 2 +- .../snaps/snap-update/snap-update.js | 2 +- .../snaps/snaps-connect/snaps-connect.js | 7 +- .../add-recipient/add-recipient.component.js | 2 +- .../send-asset-row.component.js | 2 +- .../edit-contact/edit-contact.component.js | 2 +- .../view-contact/view-contact.component.js | 2 +- .../experimental-tab.component.js | 2 +- .../networks-list/networks-list.js | 2 +- .../settings-tab/settings-tab.component.js | 2 +- ui/pages/settings/settings.component.js | 2 +- .../snaps/snaps-list-tab/snap-list-tab.js | 2 +- .../settings/snaps/view-snap/view-snap.js | 3 +- .../awaiting-signatures.js | 2 +- ui/pages/swaps/fee-card/fee-card.js | 2 +- ui/pages/swaps/import-token/import-token.js | 2 +- .../list-with-search/list-with-search.js | 3 +- .../notification-page/notification-page.js | 3 +- .../prepare-swap-page/prepare-swap-page.js | 2 +- .../quotes-loading-animation.js | 2 +- .../swaps/prepare-swap-page/review-quote.js | 7 +- .../smart-transactions-popover.js | 2 +- .../view-quote-price-difference.js | 7 +- .../slippage-buttons/slippage-buttons.js | 2 +- .../smart-transaction-status.js | 2 +- .../swaps-banner-alert/swaps-banner-alert.js | 3 +- ui/pages/token-allowance/token-allowance.js | 3 +- ui/pages/token-details/token-details-page.js | 2 +- 202 files changed, 740 insertions(+), 653 deletions(-) rename ui/components/component-library/text/deprecated/__snapshots__/{text.test.js.snap => text.test.tsx.snap} (77%) delete mode 100644 ui/components/component-library/text/deprecated/index.js create mode 100644 ui/components/component-library/text/deprecated/index.ts delete mode 100644 ui/components/component-library/text/deprecated/text.constants.js delete mode 100644 ui/components/component-library/text/deprecated/text.js rename ui/components/component-library/text/deprecated/{text.test.js => text.test.tsx} (86%) create mode 100644 ui/components/component-library/text/deprecated/text.tsx create mode 100644 ui/components/component-library/text/deprecated/text.types.ts diff --git a/ui/components/app/add-network/add-network.js b/ui/components/app/add-network/add-network.js index 0998f0b8e..4ffb947cb 100644 --- a/ui/components/app/add-network/add-network.js +++ b/ui/components/app/add-network/add-network.js @@ -36,12 +36,12 @@ import { ADD_NETWORK_ROUTE } from '../../../helpers/constants/routes'; import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import ZENDESK_URLS from '../../../helpers/constants/zendesk-url'; import { - Text, Icon, IconName, IconSize, AvatarNetwork, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { MetaMetricsNetworkEventSource } from '../../../../shared/constants/metametrics'; const AddNetwork = () => { diff --git a/ui/components/app/advanced-gas-fee-popover/advanced-gas-fee-defaults/advanced-gas-fee-defaults.js b/ui/components/app/advanced-gas-fee-popover/advanced-gas-fee-defaults/advanced-gas-fee-defaults.js index 033145d8a..b764b2351 100644 --- a/ui/components/app/advanced-gas-fee-popover/advanced-gas-fee-defaults/advanced-gas-fee-defaults.js +++ b/ui/components/app/advanced-gas-fee-popover/advanced-gas-fee-defaults/advanced-gas-fee-defaults.js @@ -16,7 +16,7 @@ import { setAdvancedGasFee } from '../../../../store/actions'; import { useGasFeeContext } from '../../../../contexts/gasFee'; import { useAdvancedGasFeePopoverContext } from '../context'; import { useI18nContext } from '../../../../hooks/useI18nContext'; -import { Text } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; const AdvancedGasFeeDefaults = () => { const t = useI18nContext(); diff --git a/ui/components/app/advanced-gas-fee-popover/advanced-gas-fee-gas-limit/advanced-gas-fee-gas-limit.js b/ui/components/app/advanced-gas-fee-popover/advanced-gas-fee-gas-limit/advanced-gas-fee-gas-limit.js index 9c8af1bb7..2c2eb0f0a 100644 --- a/ui/components/app/advanced-gas-fee-popover/advanced-gas-fee-gas-limit/advanced-gas-fee-gas-limit.js +++ b/ui/components/app/advanced-gas-fee-popover/advanced-gas-fee-gas-limit/advanced-gas-fee-gas-limit.js @@ -9,7 +9,7 @@ import Button from '../../../ui/button'; import FormField from '../../../ui/form-field'; import { useAdvancedGasFeePopoverContext } from '../context'; -import { Text } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; const validateGasLimit = (gasLimit, minimumGasLimitDec) => { return bnLessThan(gasLimit, minimumGasLimitDec) || diff --git a/ui/components/app/approve-content-card/approve-content-card.js b/ui/components/app/approve-content-card/approve-content-card.js index b9b177fe7..050e9c795 100644 --- a/ui/components/app/approve-content-card/approve-content-card.js +++ b/ui/components/app/approve-content-card/approve-content-card.js @@ -6,7 +6,7 @@ import { useSelector } from 'react-redux'; import Box from '../../ui/box/box'; import Button from '../../ui/button'; import EditGasFeeButton from '../edit-gas-fee-button/edit-gas-fee-button'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { AlignItems, BlockSize, diff --git a/ui/components/app/beta-header/index.js b/ui/components/app/beta-header/index.js index 41352723d..9ff4e2a59 100644 --- a/ui/components/app/beta-header/index.js +++ b/ui/components/app/beta-header/index.js @@ -14,12 +14,8 @@ import { import { BETA_BUGS_URL } from '../../../helpers/constants/beta'; import { hideBetaHeader } from '../../../store/actions'; -import { - ButtonIcon, - ButtonIconSize, - IconName, - Text, -} from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; +import { ButtonIcon, ButtonIconSize, IconName } from '../../component-library'; const BetaHeader = () => { const t = useI18nContext(); diff --git a/ui/components/app/cancel-speedup-popover/cancel-speedup-popover.js b/ui/components/app/cancel-speedup-popover/cancel-speedup-popover.js index 377d7eaeb..543669ca9 100644 --- a/ui/components/app/cancel-speedup-popover/cancel-speedup-popover.js +++ b/ui/components/app/cancel-speedup-popover/cancel-speedup-popover.js @@ -18,7 +18,8 @@ import Box from '../../ui/box'; import InfoTooltip from '../../ui/info-tooltip'; import Popover from '../../ui/popover'; import AppLoadingSpinner from '../app-loading-spinner'; -import { Text, Button, ButtonLink } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; +import { Button, ButtonLink } from '../../component-library'; const CancelSpeedupPopover = () => { const { diff --git a/ui/components/app/configure-snap-popup/configure-snap-popup.tsx b/ui/components/app/configure-snap-popup/configure-snap-popup.tsx index d62edd27c..62df8616d 100644 --- a/ui/components/app/configure-snap-popup/configure-snap-popup.tsx +++ b/ui/components/app/configure-snap-popup/configure-snap-popup.tsx @@ -1,9 +1,9 @@ import React from 'react'; import PropTypes from 'prop-types'; +import { Text } from '../../component-library/text/deprecated'; import { BUTTON_VARIANT, Button, - Text, Box, Modal, ModalOverlay, diff --git a/ui/components/app/confirm-data/confirm-data.js b/ui/components/app/confirm-data/confirm-data.js index b5030e0e1..017f280c5 100644 --- a/ui/components/app/confirm-data/confirm-data.js +++ b/ui/components/app/confirm-data/confirm-data.js @@ -14,7 +14,7 @@ import { useTransactionFunctionType } from '../../../hooks/useTransactionFunctio import Box from '../../ui/box/box'; import Disclosure from '../../ui/disclosure'; import TransactionDecoding from '../transaction-decoding'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; const ConfirmData = ({ txData, dataComponent }) => { const t = useI18nContext(); diff --git a/ui/components/app/confirm-gas-display/confirm-legacy-gas-display/confirm-legacy-gas-display.js b/ui/components/app/confirm-gas-display/confirm-legacy-gas-display/confirm-legacy-gas-display.js index 15e0abfb6..59419a96a 100644 --- a/ui/components/app/confirm-gas-display/confirm-legacy-gas-display/confirm-legacy-gas-display.js +++ b/ui/components/app/confirm-gas-display/confirm-legacy-gas-display/confirm-legacy-gas-display.js @@ -18,7 +18,7 @@ import TransactionDetailItem from '../../transaction-detail-item'; import UserPreferencedCurrencyDisplay from '../../user-preferenced-currency-display'; import InfoTooltip from '../../../ui/info-tooltip'; import LoadingHeartBeat from '../../../ui/loading-heartbeat'; -import { Text } from '../../../component-library/text'; +import { Text } from '../../../component-library/text/deprecated'; import { FONT_STYLE, TextVariant, diff --git a/ui/components/app/confirm-hexdata/confirm-hexdata.js b/ui/components/app/confirm-hexdata/confirm-hexdata.js index e85e46a5b..73d608b41 100644 --- a/ui/components/app/confirm-hexdata/confirm-hexdata.js +++ b/ui/components/app/confirm-hexdata/confirm-hexdata.js @@ -13,7 +13,7 @@ import { TextTransform, } from '../../../helpers/constants/design-system'; import Box from '../../ui/box'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import CopyRawData from '../transaction-decoding/components/ui/copy-raw-data'; const ConfirmHexData = ({ txData, dataHexComponent }) => { diff --git a/ui/components/app/confirm-page-container/confirm-page-container.component.js b/ui/components/app/confirm-page-container/confirm-page-container.component.js index cd489fea8..c103d6d73 100644 --- a/ui/components/app/confirm-page-container/confirm-page-container.component.js +++ b/ui/components/app/confirm-page-container/confirm-page-container.component.js @@ -22,7 +22,7 @@ import EditGasFeePopover from '../edit-gas-fee-popover/edit-gas-fee-popover'; import EditGasPopover from '../edit-gas-popover'; import ErrorMessage from '../../ui/error-message'; import { INSUFFICIENT_FUNDS_ERROR_KEY } from '../../../helpers/constants/error-keys'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { TextVariant, TextAlign, diff --git a/ui/components/app/confirm-page-container/snaps/snap-insight.js b/ui/components/app/confirm-page-container/snaps/snap-insight.js index d7fc925d7..938bc9434 100644 --- a/ui/components/app/confirm-page-container/snaps/snap-insight.js +++ b/ui/components/app/confirm-page-container/snaps/snap-insight.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import { useSelector } from 'react-redux'; import Preloader from '../../../ui/icon/preloader/preloader-icon.component'; -import { Text } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; import { AlignItems, FLEX_DIRECTION, diff --git a/ui/components/app/confirm-subtitle/confirm-subtitle.js b/ui/components/app/confirm-subtitle/confirm-subtitle.js index 1ac59dcd1..1e5a571bc 100644 --- a/ui/components/app/confirm-subtitle/confirm-subtitle.js +++ b/ui/components/app/confirm-subtitle/confirm-subtitle.js @@ -7,7 +7,7 @@ import { Color, TextVariant } from '../../../helpers/constants/design-system'; import { isNFTAssetStandard } from '../../../helpers/utils/transactions.util'; import { getShouldShowFiat } from '../../../selectors'; import { useTransactionInfo } from '../../../hooks/useTransactionInfo'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display'; const ConfirmSubTitle = ({ diff --git a/ui/components/app/confirm-title/confirm-title.js b/ui/components/app/confirm-title/confirm-title.js index 125d8d8a3..406486656 100644 --- a/ui/components/app/confirm-title/confirm-title.js +++ b/ui/components/app/confirm-title/confirm-title.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import { TransactionType } from '../../../../shared/constants/transaction'; import { PRIMARY } from '../../../helpers/constants/common'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { FONT_WEIGHT, TextVariant, diff --git a/ui/components/app/confirmation-warning-modal/confirmation-warning-modal.js b/ui/components/app/confirmation-warning-modal/confirmation-warning-modal.js index 79b53a435..120d72072 100644 --- a/ui/components/app/confirmation-warning-modal/confirmation-warning-modal.js +++ b/ui/components/app/confirmation-warning-modal/confirmation-warning-modal.js @@ -14,7 +14,8 @@ import { AlignItems, IconColor, } from '../../../helpers/constants/design-system'; -import { Icon, IconName, IconSize, Text } from '../../component-library'; +import { Icon, IconName, IconSize } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; const ConfirmationWarningModal = ({ onSubmit, onCancel }) => { const t = useI18nContext(); diff --git a/ui/components/app/contact-list/recipient-group/recipient-group.component.js b/ui/components/app/contact-list/recipient-group/recipient-group.component.js index 031761f6a..dccf6b66f 100644 --- a/ui/components/app/contact-list/recipient-group/recipient-group.component.js +++ b/ui/components/app/contact-list/recipient-group/recipient-group.component.js @@ -8,7 +8,7 @@ import { TextColor, TextVariant, } from '../../../../helpers/constants/design-system'; -import { Text } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; function addressesEqual(address1, address2) { return String(address1).toLowerCase() === String(address2).toLowerCase(); diff --git a/ui/components/app/create-new-vault/create-new-vault.js b/ui/components/app/create-new-vault/create-new-vault.js index 81e9e9063..d29d249e5 100644 --- a/ui/components/app/create-new-vault/create-new-vault.js +++ b/ui/components/app/create-new-vault/create-new-vault.js @@ -4,7 +4,7 @@ import { useI18nContext } from '../../../hooks/useI18nContext'; import TextField from '../../ui/text-field'; import Button from '../../ui/button'; import CheckBox from '../../ui/check-box'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import SrpInput from '../srp-input'; import { PASSWORD_MIN_LENGTH } from '../../../helpers/constants/common'; diff --git a/ui/components/app/custom-spending-cap/custom-spending-cap-tooltip.js b/ui/components/app/custom-spending-cap/custom-spending-cap-tooltip.js index 1c68eb297..a35e1a0f9 100644 --- a/ui/components/app/custom-spending-cap/custom-spending-cap-tooltip.js +++ b/ui/components/app/custom-spending-cap/custom-spending-cap-tooltip.js @@ -8,7 +8,8 @@ import { TextVariant, } from '../../../helpers/constants/design-system'; -import { Icon, IconName, IconSize, Text } from '../../component-library'; +import { Icon, IconName, IconSize } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; export const CustomSpendingCapTooltip = ({ tooltipContentText, diff --git a/ui/components/app/custom-spending-cap/custom-spending-cap.js b/ui/components/app/custom-spending-cap/custom-spending-cap.js index da9033c07..70bbdb9af 100644 --- a/ui/components/app/custom-spending-cap/custom-spending-cap.js +++ b/ui/components/app/custom-spending-cap/custom-spending-cap.js @@ -8,7 +8,8 @@ import { addHexPrefix } from 'ethereumjs-util'; import { I18nContext } from '../../../contexts/i18n'; import Box from '../../ui/box'; import FormField from '../../ui/form-field'; -import { Text, ButtonLink, Icon, IconName } from '../../component-library'; +import { ButtonLink, Icon, IconName } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { AlignItems, DISPLAY, diff --git a/ui/components/app/detected-token/detected-token-address/detected-token-address.js b/ui/components/app/detected-token/detected-token-address/detected-token-address.js index 2e752bce1..dd9595d2f 100644 --- a/ui/components/app/detected-token/detected-token-address/detected-token-address.js +++ b/ui/components/app/detected-token/detected-token-address/detected-token-address.js @@ -15,7 +15,7 @@ import { } from '../../../../helpers/constants/design-system'; import { shortenAddress } from '../../../../helpers/utils/util'; -import { Text } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; const DetectedTokenAddress = ({ tokenAddress }) => { const t = useI18nContext(); diff --git a/ui/components/app/detected-token/detected-token-aggregators/detected-token-aggregators.js b/ui/components/app/detected-token/detected-token-aggregators/detected-token-aggregators.js index ac3af6bff..0bf574c75 100644 --- a/ui/components/app/detected-token/detected-token-aggregators/detected-token-aggregators.js +++ b/ui/components/app/detected-token/detected-token-aggregators/detected-token-aggregators.js @@ -8,7 +8,8 @@ import { FontWeight, TextVariant, } from '../../../../helpers/constants/design-system'; -import { Text, Box, ButtonLink } from '../../../component-library'; +import { Box, ButtonLink } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; const NUMBER_OF_AGGREGATORS_TO_DISPLAY = 2; diff --git a/ui/components/app/detected-token/detected-token-ignored-popover/detected-token-ignored-popover.js b/ui/components/app/detected-token/detected-token-ignored-popover/detected-token-ignored-popover.js index 708b078db..f5635c8e4 100644 --- a/ui/components/app/detected-token/detected-token-ignored-popover/detected-token-ignored-popover.js +++ b/ui/components/app/detected-token/detected-token-ignored-popover/detected-token-ignored-popover.js @@ -6,7 +6,7 @@ import { useI18nContext } from '../../../../hooks/useI18nContext'; import Popover from '../../../ui/popover'; import Button from '../../../ui/button'; import { TextVariant } from '../../../../helpers/constants/design-system'; -import { Text } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; const DetectedTokenIgnoredPopover = ({ partiallyIgnoreDetectedTokens, diff --git a/ui/components/app/detected-token/detected-token-values/detected-token-values.js b/ui/components/app/detected-token/detected-token-values/detected-token-values.js index 6d1a95470..e4f71353b 100644 --- a/ui/components/app/detected-token/detected-token-values/detected-token-values.js +++ b/ui/components/app/detected-token/detected-token-values/detected-token-values.js @@ -12,7 +12,8 @@ import { import { useTokenTracker } from '../../../../hooks/useTokenTracker'; import { useTokenFiatAmount } from '../../../../hooks/useTokenFiatAmount'; import { getUseCurrencyRateCheck } from '../../../../selectors'; -import { Text, Box } from '../../../component-library'; +import { Box } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; const DetectedTokenValues = ({ token, diff --git a/ui/components/app/edit-gas-display/edit-gas-display.component.js b/ui/components/app/edit-gas-display/edit-gas-display.component.js index 6bd1ed4cc..49f7d9a1d 100644 --- a/ui/components/app/edit-gas-display/edit-gas-display.component.js +++ b/ui/components/app/edit-gas-display/edit-gas-display.component.js @@ -12,7 +12,7 @@ import { TextColor, TextVariant, } from '../../../helpers/constants/design-system'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { areDappSuggestedAndTxParamGasFeesTheSame } from '../../../helpers/utils/confirm-tx.util'; import InfoTooltip from '../../ui/info-tooltip'; diff --git a/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.js b/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.js index 70fb157e1..b06bc0c11 100644 --- a/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.js +++ b/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.js @@ -13,7 +13,8 @@ import { useI18nContext } from '../../../hooks/useI18nContext'; import { useTransactionEventFragment } from '../../../hooks/useTransactionEventFragment'; import { useTransactionModalContext } from '../../../contexts/transaction-modal'; import InfoTooltip from '../../ui/info-tooltip/info-tooltip'; -import { Icon, IconName, IconSize, Text } from '../../component-library'; +import { Icon, IconName, IconSize } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; export default function EditGasFeeButton({ userAcknowledgedGasMissing }) { const t = useI18nContext(); diff --git a/ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.js b/ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.js index d057f042b..5919b2aa8 100644 --- a/ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.js +++ b/ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.js @@ -15,7 +15,7 @@ import { INSUFFICIENT_FUNDS_ERROR_KEY } from '../../../helpers/constants/error-k import { useGasFeeContext } from '../../../contexts/gasFee'; import AppLoadingSpinner from '../app-loading-spinner'; import ZENDESK_URLS from '../../../helpers/constants/zendesk-url'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import EditGasItem from './edit-gas-item'; import NetworkStatistics from './network-statistics'; diff --git a/ui/components/app/edit-gas-fee-popover/edit-gas-tooltip/edit-gas-tooltip.js b/ui/components/app/edit-gas-fee-popover/edit-gas-tooltip/edit-gas-tooltip.js index 2d700e3c7..975a2c6f0 100644 --- a/ui/components/app/edit-gas-fee-popover/edit-gas-tooltip/edit-gas-tooltip.js +++ b/ui/components/app/edit-gas-fee-popover/edit-gas-tooltip/edit-gas-tooltip.js @@ -11,7 +11,7 @@ import { } from '../../../../helpers/constants/design-system'; import { isMetamaskSuggestedGasEstimate } from '../../../../helpers/utils/gas'; import { roundToDecimalPlacesRemovingExtraZeroes } from '../../../../helpers/utils/util'; -import { Text } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; const EditGasToolTip = ({ editGasMode, diff --git a/ui/components/app/edit-gas-fee-popover/network-statistics/network-statistics.js b/ui/components/app/edit-gas-fee-popover/network-statistics/network-statistics.js index 6a14f655b..06bc0e81b 100644 --- a/ui/components/app/edit-gas-fee-popover/network-statistics/network-statistics.js +++ b/ui/components/app/edit-gas-fee-popover/network-statistics/network-statistics.js @@ -8,7 +8,7 @@ import { isNullish } from '../../../../helpers/utils/util'; import { formatGasFeeOrFeeRange } from '../../../../helpers/utils/gas'; import { I18nContext } from '../../../../contexts/i18n'; import { useGasFeeContext } from '../../../../contexts/gasFee'; -import { Text } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; import { BaseFeeTooltip, PriorityFeeTooltip } from './tooltips'; import StatusSlider from './status-slider'; diff --git a/ui/components/app/gas-details-item/gas-details-item-title/gas-details-item-title.js b/ui/components/app/gas-details-item/gas-details-item-title/gas-details-item-title.js index 9e7c267dd..060a43d55 100644 --- a/ui/components/app/gas-details-item/gas-details-item-title/gas-details-item-title.js +++ b/ui/components/app/gas-details-item/gas-details-item-title/gas-details-item-title.js @@ -6,7 +6,7 @@ import { useI18nContext } from '../../../../hooks/useI18nContext'; import { getIsMainnet } from '../../../../selectors'; import Box from '../../../ui/box'; import InfoTooltip from '../../../ui/info-tooltip/info-tooltip'; -import { Text } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; const GasDetailsItemTitle = () => { const t = useI18nContext(); diff --git a/ui/components/app/ledger-instruction-field/ledger-instruction-field.js b/ui/components/app/ledger-instruction-field/ledger-instruction-field.js index 5de3aa97a..0e8ba0a24 100644 --- a/ui/components/app/ledger-instruction-field/ledger-instruction-field.js +++ b/ui/components/app/ledger-instruction-field/ledger-instruction-field.js @@ -19,7 +19,8 @@ import { getLedgerTransportStatus, } from '../../../ducks/app/app'; -import { BannerAlert, ButtonLink, Text } from '../../component-library'; +import { BannerAlert, ButtonLink } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { SEVERITIES, diff --git a/ui/components/app/loading-network-screen/loading-network-screen.component.js b/ui/components/app/loading-network-screen/loading-network-screen.component.js index 61c7c93aa..71d686691 100644 --- a/ui/components/app/loading-network-screen/loading-network-screen.component.js +++ b/ui/components/app/loading-network-screen/loading-network-screen.component.js @@ -10,8 +10,8 @@ import { Icon, IconName, IconSize, - Text, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { DISPLAY, IconColor, diff --git a/ui/components/app/modals/contract-details-modal/contract-details-modal.js b/ui/components/app/modals/contract-details-modal/contract-details-modal.js index db14cb8bc..3b976cd2a 100644 --- a/ui/components/app/modals/contract-details-modal/contract-details-modal.js +++ b/ui/components/app/modals/contract-details-modal/contract-details-modal.js @@ -24,7 +24,8 @@ import { useCopyToClipboard } from '../../../../hooks/useCopyToClipboard'; import { getAddressBookEntry } from '../../../../selectors'; import { TokenStandard } from '../../../../../shared/constants/transaction'; import NftCollectionImage from '../../../ui/nft-collection-image/nft-collection-image'; -import { ButtonIcon, IconName, Text } from '../../../component-library'; +import { ButtonIcon, IconName } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; export default function ContractDetailsModal({ onClose, diff --git a/ui/components/app/modals/customize-nonce/customize-nonce.component.js b/ui/components/app/modals/customize-nonce/customize-nonce.component.js index 1d87cbd54..765c8f527 100644 --- a/ui/components/app/modals/customize-nonce/customize-nonce.component.js +++ b/ui/components/app/modals/customize-nonce/customize-nonce.component.js @@ -17,8 +17,8 @@ import { ButtonIconSize, ButtonLink, IconName, - Text, } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; const CustomizeNonce = ({ hideModal, diff --git a/ui/components/app/modals/eth-sign-modal/eth-sign-modal.js b/ui/components/app/modals/eth-sign-modal/eth-sign-modal.js index 47b056a7b..a2d5d09fb 100644 --- a/ui/components/app/modals/eth-sign-modal/eth-sign-modal.js +++ b/ui/components/app/modals/eth-sign-modal/eth-sign-modal.js @@ -14,8 +14,8 @@ import { IconName, IconSize, Label, - Text, } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; import { AlignItems, Display, diff --git a/ui/components/app/modals/export-private-key-modal/export-private-key-modal.component.js b/ui/components/app/modals/export-private-key-modal/export-private-key-modal.component.js index 49c4f7be2..2b26421b7 100644 --- a/ui/components/app/modals/export-private-key-modal/export-private-key-modal.component.js +++ b/ui/components/app/modals/export-private-key-modal/export-private-key-modal.component.js @@ -8,8 +8,8 @@ import { BUTTON_VARIANT, BannerAlert, Button, - Text, } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; import AccountModalContainer from '../account-modal-container'; import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils'; import { diff --git a/ui/components/app/modals/hold-to-reveal-modal/hold-to-reveal-modal.js b/ui/components/app/modals/hold-to-reveal-modal/hold-to-reveal-modal.js index 2537d1cd2..c4f35523b 100644 --- a/ui/components/app/modals/hold-to-reveal-modal/hold-to-reveal-modal.js +++ b/ui/components/app/modals/hold-to-reveal-modal/hold-to-reveal-modal.js @@ -3,13 +3,13 @@ import React, { useContext } from 'react'; import withModalProps from '../../../../helpers/higher-order-components/with-modal-props'; import Box from '../../../ui/box'; import { - Text, Button, BUTTON_SIZES, BUTTON_VARIANT, ButtonIcon, IconName, } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; import { AlignItems, Display, diff --git a/ui/components/app/network-account-balance-header/network-account-balance-header.js b/ui/components/app/network-account-balance-header/network-account-balance-header.js index 98c91acfe..29a97becc 100644 --- a/ui/components/app/network-account-balance-header/network-account-balance-header.js +++ b/ui/components/app/network-account-balance-header/network-account-balance-header.js @@ -15,7 +15,7 @@ import { import Box from '../../ui/box/box'; import { I18nContext } from '../../../contexts/i18n'; import { CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP } from '../../../../shared/constants/network'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; export default function NetworkAccountBalanceHeader({ networkName, diff --git a/ui/components/app/nft-default-image/nft-default-image.js b/ui/components/app/nft-default-image/nft-default-image.js index 54c5d688d..3945a9108 100644 --- a/ui/components/app/nft-default-image/nft-default-image.js +++ b/ui/components/app/nft-default-image/nft-default-image.js @@ -12,7 +12,7 @@ import { BackgroundColor, } from '../../../helpers/constants/design-system'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import Box from '../../ui/box/box'; export default function NftDefaultImage({ diff --git a/ui/components/app/nft-details/nft-details.js b/ui/components/app/nft-details/nft-details.js index c0a9cbd33..491506339 100644 --- a/ui/components/app/nft-details/nft-details.js +++ b/ui/components/app/nft-details/nft-details.js @@ -51,7 +51,8 @@ import { AssetType, TokenStandard, } from '../../../../shared/constants/transaction'; -import { ButtonIcon, IconName, Text } from '../../component-library'; +import { ButtonIcon, IconName } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import Tooltip from '../../ui/tooltip'; import { decWEIToDecETH } from '../../../../shared/modules/conversion.utils'; import { NftItem } from '../../multichain/nft-item'; diff --git a/ui/components/app/nfts-detection-notice/nfts-detection-notice.js b/ui/components/app/nfts-detection-notice/nfts-detection-notice.js index f93718906..59e671367 100644 --- a/ui/components/app/nfts-detection-notice/nfts-detection-notice.js +++ b/ui/components/app/nfts-detection-notice/nfts-detection-notice.js @@ -2,7 +2,8 @@ import React from 'react'; import { useHistory } from 'react-router-dom'; import Box from '../../ui/box'; import Dialog from '../../ui/dialog'; -import { Icon, IconName, Text } from '../../component-library'; +import { Icon, IconName } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { TextVariant, TextAlign, diff --git a/ui/components/app/nfts-tab/nfts-tab.js b/ui/components/app/nfts-tab/nfts-tab.js index 2e1918c0d..530e367c8 100644 --- a/ui/components/app/nfts-tab/nfts-tab.js +++ b/ui/components/app/nfts-tab/nfts-tab.js @@ -21,7 +21,8 @@ import { showImportNftsModal, } from '../../../store/actions'; import { useNftsCollections } from '../../../hooks/useNftsCollections'; -import { Box, ButtonLink, IconName, Text } from '../../component-library'; +import { Box, ButtonLink, IconName } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import NftsDetectionNotice from '../nfts-detection-notice'; import ZENDESK_URLS from '../../../helpers/constants/zendesk-url'; diff --git a/ui/components/app/permission-cell/permission-cell-options.js b/ui/components/app/permission-cell/permission-cell-options.js index ec7dda4cd..768f23e05 100644 --- a/ui/components/app/permission-cell/permission-cell-options.js +++ b/ui/components/app/permission-cell/permission-cell-options.js @@ -3,7 +3,8 @@ import PropTypes from 'prop-types'; import { useDispatch } from 'react-redux'; import Box from '../../ui/box'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import { IconName, ButtonIcon, Text } from '../../component-library'; +import { IconName, ButtonIcon } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { Menu, MenuItem } from '../../ui/menu'; import { TextColor, diff --git a/ui/components/app/permission-cell/permission-cell.js b/ui/components/app/permission-cell/permission-cell.js index c5fca8fa8..cd4b813b3 100644 --- a/ui/components/app/permission-cell/permission-cell.js +++ b/ui/components/app/permission-cell/permission-cell.js @@ -11,13 +11,8 @@ import { TextColor, TextVariant, } from '../../../helpers/constants/design-system'; -import { - AvatarIcon, - Text, - Icon, - IconName, - IconSize, -} from '../../component-library'; +import { AvatarIcon, Icon, IconName, IconSize } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { formatDate } from '../../../helpers/utils/util'; import { useI18nContext } from '../../../hooks/useI18nContext'; import Tooltip from '../../ui/tooltip'; diff --git a/ui/components/app/qr-hardware-popover/qr-hardware-sign-request/player.js b/ui/components/app/qr-hardware-popover/qr-hardware-sign-request/player.js index 1ac48080b..9dfdbf732 100644 --- a/ui/components/app/qr-hardware-popover/qr-hardware-sign-request/player.js +++ b/ui/components/app/qr-hardware-popover/qr-hardware-sign-request/player.js @@ -11,7 +11,7 @@ import { TextAlign, } from '../../../../helpers/constants/design-system'; import { PageContainerFooter } from '../../../ui/page-container'; -import { Text } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; const Player = ({ type, cbor, cancelQRHardwareSignRequest, toRead }) => { const t = useI18nContext(); diff --git a/ui/components/app/recovery-phrase-reminder/recovery-phrase-reminder.js b/ui/components/app/recovery-phrase-reminder/recovery-phrase-reminder.js index d21a3f7a6..c6f496052 100644 --- a/ui/components/app/recovery-phrase-reminder/recovery-phrase-reminder.js +++ b/ui/components/app/recovery-phrase-reminder/recovery-phrase-reminder.js @@ -17,7 +17,7 @@ import { TextColor, } from '../../../helpers/constants/design-system'; import { ONBOARDING_UNLOCK_ROUTE } from '../../../helpers/constants/routes'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; export default function RecoveryPhraseReminder({ onConfirm, hasBackedUp }) { const t = useI18nContext(); diff --git a/ui/components/app/security-provider-banner-message/security-provider-banner-message.js b/ui/components/app/security-provider-banner-message/security-provider-banner-message.js index fdaba451f..48ed96363 100644 --- a/ui/components/app/security-provider-banner-message/security-provider-banner-message.js +++ b/ui/components/app/security-provider-banner-message/security-provider-banner-message.js @@ -8,7 +8,8 @@ import { } from '../../../helpers/constants/design-system'; import { SECURITY_PROVIDER_MESSAGE_SEVERITY } from '../../../../shared/constants/security-provider'; import { I18nContext } from '../../../../.storybook/i18n'; -import { BannerAlert, ButtonLink, Text } from '../../component-library'; +import { BannerAlert, ButtonLink } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; export default function SecurityProviderBannerMessage({ securityProviderResponse, diff --git a/ui/components/app/set-approval-for-all-warning/set-approval-for-all-warning.js b/ui/components/app/set-approval-for-all-warning/set-approval-for-all-warning.js index c311eaeb2..715535445 100644 --- a/ui/components/app/set-approval-for-all-warning/set-approval-for-all-warning.js +++ b/ui/components/app/set-approval-for-all-warning/set-approval-for-all-warning.js @@ -16,10 +16,10 @@ import { shortenAddress } from '../../../helpers/utils/util'; import { Icon, IconName, - Text, Button, BUTTON_VARIANT, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; const SetApproveForAllWarning = ({ collectionName, diff --git a/ui/components/app/signature-request-original/signature-request-original.component.js b/ui/components/app/signature-request-original/signature-request-original.component.js index 6dc18e4a4..47dfcb8d3 100644 --- a/ui/components/app/signature-request-original/signature-request-original.component.js +++ b/ui/components/app/signature-request-original/signature-request-original.component.js @@ -34,7 +34,8 @@ import { import ConfirmPageContainerNavigation from '../confirm-page-container/confirm-page-container-navigation'; import SecurityProviderBannerMessage from '../security-provider-banner-message/security-provider-banner-message'; ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) -import { Icon, IconName, Text } from '../../component-library'; +import { Icon, IconName } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import Box from '../../ui/box/box'; ///: END:ONLY_INCLUDE_IN import SignatureRequestHeader from '../signature-request-header'; diff --git a/ui/components/app/signature-request-siwe/signature-request-siwe-message/signature-request-siwe-message.js b/ui/components/app/signature-request-siwe/signature-request-siwe-message/signature-request-siwe-message.js index 565703ef2..ef94acc17 100644 --- a/ui/components/app/signature-request-siwe/signature-request-siwe-message/signature-request-siwe-message.js +++ b/ui/components/app/signature-request-siwe/signature-request-siwe-message/signature-request-siwe-message.js @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import Box from '../../../ui/box'; -import { Text } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; import { FLEX_DIRECTION, diff --git a/ui/components/app/signature-request-siwe/signature-request-siwe-tag/index.js b/ui/components/app/signature-request-siwe/signature-request-siwe-tag/index.js index fc4eef706..948041406 100644 --- a/ui/components/app/signature-request-siwe/signature-request-siwe-tag/index.js +++ b/ui/components/app/signature-request-siwe/signature-request-siwe-tag/index.js @@ -9,7 +9,7 @@ import { TextColor, } from '../../../../helpers/constants/design-system'; import Box from '../../../ui/box'; -import { Text } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; const SignatureRequestSIWETag = ({ text }) => { return ( diff --git a/ui/components/app/signature-request-siwe/signature-request-siwe.js b/ui/components/app/signature-request-siwe/signature-request-siwe.js index ddd4319e5..68e1f73d6 100644 --- a/ui/components/app/signature-request-siwe/signature-request-siwe.js +++ b/ui/components/app/signature-request-siwe/signature-request-siwe.js @@ -5,7 +5,8 @@ import { useHistory } from 'react-router-dom'; import log from 'loglevel'; import { isValidSIWEOrigin } from '@metamask/controller-utils'; import { ethErrors, serializeError } from 'eth-rpc-errors'; -import { BannerAlert, Text } from '../../component-library'; +import { BannerAlert } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import Popover from '../../ui/popover'; import Checkbox from '../../ui/check-box'; import Button from '../../ui/button'; diff --git a/ui/components/app/signature-request/signature-request-message/signature-request-message.js b/ui/components/app/signature-request/signature-request-message/signature-request-message.js index 52322d084..fad259f1d 100644 --- a/ui/components/app/signature-request/signature-request-message/signature-request-message.js +++ b/ui/components/app/signature-request/signature-request-message/signature-request-message.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import { debounce } from 'lodash'; import { I18nContext } from '../../../../contexts/i18n'; import Box from '../../../ui/box'; -import { Text } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; import { Display, FlexDirection, diff --git a/ui/components/app/signature-request/signature-request.component.js b/ui/components/app/signature-request/signature-request.component.js index e2246f2b5..601d73e35 100644 --- a/ui/components/app/signature-request/signature-request.component.js +++ b/ui/components/app/signature-request/signature-request.component.js @@ -41,8 +41,8 @@ import { Icon, IconName, ///: END:ONLY_INCLUDE_IN - Text, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import Footer from './signature-request-footer'; import Message from './signature-request-message'; diff --git a/ui/components/app/snaps/install-error/install-error.js b/ui/components/app/snaps/install-error/install-error.js index dad100bda..e8003192b 100644 --- a/ui/components/app/snaps/install-error/install-error.js +++ b/ui/components/app/snaps/install-error/install-error.js @@ -13,7 +13,8 @@ import { TextVariant, } from '../../../../helpers/constants/design-system'; import ActionableMessage from '../../../ui/actionable-message/actionable-message'; -import { AvatarIcon, IconSize, Text } from '../../../component-library'; +import { AvatarIcon, IconSize } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; const InstallError = ({ title, error, description, iconName }) => { return ( diff --git a/ui/components/app/snaps/snap-authorship-expanded/snap-authorship-expanded.js b/ui/components/app/snaps/snap-authorship-expanded/snap-authorship-expanded.js index 8c5e54a10..c3efb4e24 100644 --- a/ui/components/app/snaps/snap-authorship-expanded/snap-authorship-expanded.js +++ b/ui/components/app/snaps/snap-authorship-expanded/snap-authorship-expanded.js @@ -25,7 +25,8 @@ import { removeSnapIdPrefix, } from '../../../../helpers/utils/util'; -import { Text, ButtonLink } from '../../../component-library'; +import { ButtonLink } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; import { getTargetSubjectMetadata } from '../../../../selectors'; import SnapAvatar from '../snap-avatar'; import { useI18nContext } from '../../../../hooks/useI18nContext'; diff --git a/ui/components/app/snaps/snap-authorship-header/snap-authorship-header.js b/ui/components/app/snaps/snap-authorship-header/snap-authorship-header.js index 4f99c2162..7945751e2 100644 --- a/ui/components/app/snaps/snap-authorship-header/snap-authorship-header.js +++ b/ui/components/app/snaps/snap-authorship-header/snap-authorship-header.js @@ -19,7 +19,7 @@ import { removeSnapIdPrefix, } from '../../../../helpers/utils/util'; -import { Text } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; import { getTargetSubjectMetadata } from '../../../../selectors'; import SnapAvatar from '../snap-avatar'; import SnapVersion from '../snap-version/snap-version'; diff --git a/ui/components/app/snaps/snap-connect-cell/snap-connect-cell.js b/ui/components/app/snaps/snap-connect-cell/snap-connect-cell.js index a62b5ff1d..9ca3e434f 100644 --- a/ui/components/app/snaps/snap-connect-cell/snap-connect-cell.js +++ b/ui/components/app/snaps/snap-connect-cell/snap-connect-cell.js @@ -9,13 +9,8 @@ import { FontWeight, } from '../../../../helpers/constants/design-system'; import { getSnapName } from '../../../../helpers/utils/util'; -import { - Icon, - IconName, - IconSize, - Text, - ValidTag, -} from '../../../component-library'; +import { Icon, IconName, IconSize, ValidTag } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; import Tooltip from '../../../ui/tooltip/tooltip'; import { useI18nContext } from '../../../../hooks/useI18nContext'; import SnapAvatar from '../snap-avatar/snap-avatar'; diff --git a/ui/components/app/snaps/snap-delineator/snap-delineator.js b/ui/components/app/snaps/snap-delineator/snap-delineator.js index de872cff3..93d2097ae 100644 --- a/ui/components/app/snaps/snap-delineator/snap-delineator.js +++ b/ui/components/app/snaps/snap-delineator/snap-delineator.js @@ -12,12 +12,8 @@ import { TextColor, } from '../../../../helpers/constants/design-system'; import Box from '../../../ui/box'; -import { - AvatarIcon, - Text, - IconName, - IconSize, -} from '../../../component-library'; +import { AvatarIcon, IconName, IconSize } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; import { DelineatorType, getDelineatorTitle, diff --git a/ui/components/app/snaps/snap-install-warning/snap-install-warning.js b/ui/components/app/snaps/snap-install-warning/snap-install-warning.js index e4337c3d6..83960e879 100644 --- a/ui/components/app/snaps/snap-install-warning/snap-install-warning.js +++ b/ui/components/app/snaps/snap-install-warning/snap-install-warning.js @@ -16,7 +16,8 @@ import { } from '../../../../helpers/constants/design-system'; import Popover from '../../../ui/popover'; import Button from '../../../ui/button'; -import { AvatarIcon, Text, IconName } from '../../../component-library'; +import { AvatarIcon, IconName } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; import Box from '../../../ui/box/box'; /** diff --git a/ui/components/app/snaps/snap-privacy-warning/snap-privacy-warning.js b/ui/components/app/snaps/snap-privacy-warning/snap-privacy-warning.js index 0d9e1d99b..45a55a959 100644 --- a/ui/components/app/snaps/snap-privacy-warning/snap-privacy-warning.js +++ b/ui/components/app/snaps/snap-privacy-warning/snap-privacy-warning.js @@ -12,8 +12,8 @@ import { ButtonLink, IconName, IconSize, - Text, } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; import { AlignItems, BackgroundColor, diff --git a/ui/components/app/snaps/snap-settings-card/snap-settings-card.js b/ui/components/app/snaps/snap-settings-card/snap-settings-card.js index 6f7fc6822..54703c999 100644 --- a/ui/components/app/snaps/snap-settings-card/snap-settings-card.js +++ b/ui/components/app/snaps/snap-settings-card/snap-settings-card.js @@ -12,7 +12,8 @@ import { IconColor, TextVariant, } from '../../../../helpers/constants/design-system'; -import { Icon, IconName, IconSize, Text } from '../../../component-library'; +import { Icon, IconName, IconSize } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; import SnapAvatar from '../snap-avatar'; const SnapSettingsCard = ({ name, packageName, onClick, snapId }) => { diff --git a/ui/components/app/snaps/snap-ui-renderer/snap-ui-renderer.js b/ui/components/app/snaps/snap-ui-renderer/snap-ui-renderer.js index 37d83c2c9..60033d2d1 100644 --- a/ui/components/app/snaps/snap-ui-renderer/snap-ui-renderer.js +++ b/ui/components/app/snaps/snap-ui-renderer/snap-ui-renderer.js @@ -17,7 +17,7 @@ import { useI18nContext } from '../../../../hooks/useI18nContext'; import Box from '../../../ui/box'; import { getSnapName } from '../../../../helpers/utils/util'; import { getTargetSubjectMetadata } from '../../../../selectors'; -import { Text } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; import { Copyable } from '../copyable'; import { DelineatorType } from '../../../../helpers/constants/snaps'; diff --git a/ui/components/app/snaps/snap-version/snap-version.js b/ui/components/app/snaps/snap-version/snap-version.js index f70653540..88dd90b4a 100644 --- a/ui/components/app/snaps/snap-version/snap-version.js +++ b/ui/components/app/snaps/snap-version/snap-version.js @@ -15,8 +15,8 @@ import { Icon, IconName, IconSize, - Text, } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; import Preloader from '../../../ui/icon/preloader/preloader-icon.component'; const SnapVersion = ({ version, url }) => { diff --git a/ui/components/app/srp-input/srp-input.js b/ui/components/app/srp-input/srp-input.js index be990e3cf..e23460f6b 100644 --- a/ui/components/app/srp-input/srp-input.js +++ b/ui/components/app/srp-input/srp-input.js @@ -11,7 +11,7 @@ import { TextAlign, TextVariant, } from '../../../helpers/constants/design-system'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { parseSecretRecoveryPhrase } from './parse-secret-recovery-phrase'; const defaultNumberOfWords = 12; diff --git a/ui/components/app/srp-quiz-modal/QuizContent/QuizContent.tsx b/ui/components/app/srp-quiz-modal/QuizContent/QuizContent.tsx index 67b1f4c06..6a44f6676 100644 --- a/ui/components/app/srp-quiz-modal/QuizContent/QuizContent.tsx +++ b/ui/components/app/srp-quiz-modal/QuizContent/QuizContent.tsx @@ -9,7 +9,8 @@ import { TextVariant, } from '../../../../helpers/constants/design-system'; import { useI18nContext } from '../../../../hooks/useI18nContext'; -import { Button, Text, Box } from '../../../component-library'; +import { Button, Box } from '../../../component-library'; +import { Text } from '../../../component-library/text/deprecated'; import { IQuizInformationProps } from '../types'; export default function QuizContent({ diff --git a/ui/components/app/terms-of-use-popup/terms-of-use-popup.js b/ui/components/app/terms-of-use-popup/terms-of-use-popup.js index 1b8097a70..46126b7de 100644 --- a/ui/components/app/terms-of-use-popup/terms-of-use-popup.js +++ b/ui/components/app/terms-of-use-popup/terms-of-use-popup.js @@ -11,12 +11,12 @@ import { TextColor, } from '../../../helpers/constants/design-system'; import { - Text, Button, BUTTON_VARIANT, ButtonLink, Label, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import Box from '../../ui/box'; import CheckBox from '../../ui/check-box/check-box.component'; import { diff --git a/ui/components/app/transaction-alerts/transaction-alerts.js b/ui/components/app/transaction-alerts/transaction-alerts.js index 72b65c991..ed8becda8 100644 --- a/ui/components/app/transaction-alerts/transaction-alerts.js +++ b/ui/components/app/transaction-alerts/transaction-alerts.js @@ -6,7 +6,8 @@ import { PriorityLevels } from '../../../../shared/constants/gas'; import { submittedPendingTransactionsSelector } from '../../../selectors'; import { useGasFeeContext } from '../../../contexts/gasFee'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import { BannerAlert, ButtonLink, Text } from '../../component-library'; +import { BannerAlert, ButtonLink } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import SimulationErrorMessage from '../../ui/simulation-error-message'; import { SEVERITIES } from '../../../helpers/constants/design-system'; import ZENDESK_URLS from '../../../helpers/constants/zendesk-url'; diff --git a/ui/components/app/transaction-list-item-details/transaction-list-item-details.component.js b/ui/components/app/transaction-list-item-details/transaction-list-item-details.component.js index 502f62d94..d729c5dc1 100644 --- a/ui/components/app/transaction-list-item-details/transaction-list-item-details.component.js +++ b/ui/components/app/transaction-list-item-details/transaction-list-item-details.component.js @@ -13,7 +13,8 @@ import CancelButton from '../cancel-button'; import Popover from '../../ui/popover'; ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) import Box from '../../ui/box/box'; -import { Icon, IconName, Text } from '../../component-library'; +import { Icon, IconName } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { IconColor } from '../../../helpers/constants/design-system'; ///: END:ONLY_INCLUDE_IN import { SECOND } from '../../../../shared/constants/time'; diff --git a/ui/components/app/whats-new-popup/whats-new-popup.js b/ui/components/app/whats-new-popup/whats-new-popup.js index 5743cc841..8b8be5b48 100644 --- a/ui/components/app/whats-new-popup/whats-new-popup.js +++ b/ui/components/app/whats-new-popup/whats-new-popup.js @@ -13,8 +13,8 @@ import { ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) IconName, ///: END:ONLY_INCLUDE_IN - Text, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { updateViewedNotifications } from '../../../store/actions'; import { getTranslatedUINotifications } from '../../../../shared/notifications'; import { getSortedAnnouncementsToShow } from '../../../selectors'; diff --git a/ui/components/component-library/avatar-base/avatar-base.tsx b/ui/components/component-library/avatar-base/avatar-base.tsx index 164fdf5a4..516959f32 100644 --- a/ui/components/component-library/avatar-base/avatar-base.tsx +++ b/ui/components/component-library/avatar-base/avatar-base.tsx @@ -13,7 +13,7 @@ import { TextTransform, } from '../../../helpers/constants/design-system'; -import { Text, ValidTag } from '../text'; +import { Text } from '../text/deprecated'; import { AvatarBaseProps, AvatarBaseSize } from './avatar-base.types'; @@ -47,7 +47,7 @@ export const AvatarBase = forwardRef( className, )} ref={ref} - as={ValidTag.Div} + as="div" display={Display.Flex} justifyContent={JustifyContent.center} alignItems={AlignItems.center} diff --git a/ui/components/component-library/avatar-base/avatar-base.types.ts b/ui/components/component-library/avatar-base/avatar-base.types.ts index 11bc51ac7..bca4653f6 100644 --- a/ui/components/component-library/avatar-base/avatar-base.types.ts +++ b/ui/components/component-library/avatar-base/avatar-base.types.ts @@ -3,7 +3,7 @@ import { BorderColor, TextColor, } from '../../../helpers/constants/design-system'; -import { TextProps } from '../text'; +import type { TextProps } from '../text/deprecated'; export enum AvatarBaseSize { Xs = 'xs', diff --git a/ui/components/component-library/avatar-token/avatar-token.stories.js b/ui/components/component-library/avatar-token/avatar-token.stories.js index 4262f30d1..9c84fd7d5 100644 --- a/ui/components/component-library/avatar-token/avatar-token.stories.js +++ b/ui/components/component-library/avatar-token/avatar-token.stories.js @@ -10,13 +10,8 @@ import { import Box from '../../ui/box/box'; -import { - AvatarNetwork, - BUTTON_LINK_SIZES, - BadgeWrapper, - ButtonLink, - Text, -} from '..'; +import { AvatarNetwork, BUTTON_LINK_SIZES, BadgeWrapper, ButtonLink } from '..'; +import { Text } from '../text/deprecated'; import README from './README.mdx'; diff --git a/ui/components/component-library/banner-base/banner-base.js b/ui/components/component-library/banner-base/banner-base.js index cc9f5575e..a2c790815 100644 --- a/ui/components/component-library/banner-base/banner-base.js +++ b/ui/components/component-library/banner-base/banner-base.js @@ -12,7 +12,8 @@ import { import Box from '../../ui/box'; -import { ButtonLink, Text, IconName, ButtonIcon } from '..'; +import { ButtonLink, IconName, ButtonIcon } from '..'; +import { Text } from '../text/deprecated'; export const BannerBase = ({ className, @@ -92,7 +93,7 @@ BannerBase.propTypes = { /** * Additional props to pass to the `Text` component used for the `title` text */ - titleProps: PropTypes.shape(Text.PropTypes), + titleProps: PropTypes.shape(Text.propTypes), /** * The description is the content area below BannerBase title */ @@ -100,7 +101,7 @@ BannerBase.propTypes = { /** * Additional props to pass to the `Text` component used for the `description` text */ - descriptionProps: PropTypes.shape(Text.PropTypes), + descriptionProps: PropTypes.shape(Text.propTypes), /** * The children is an alternative to using the description prop for BannerBase content below the title */ @@ -112,7 +113,7 @@ BannerBase.propTypes = { /** * Props for action button (ButtonLink) of the BannerBase below the children */ - actionButtonProps: PropTypes.shape(ButtonLink.PropTypes), + actionButtonProps: PropTypes.shape(ButtonLink.propTypes), /** * The onClick handler for the action button (ButtonLink) */ @@ -129,7 +130,7 @@ BannerBase.propTypes = { /** * The props to pass to the close button */ - closeButtonProps: PropTypes.shape(ButtonIcon.PropTypes), + closeButtonProps: PropTypes.shape(ButtonIcon.propTypes), /** * An additional className to apply to the BannerBase */ diff --git a/ui/components/component-library/button-base/button-base.js b/ui/components/component-library/button-base/button-base.js index 7c4f16e42..435b0b62e 100644 --- a/ui/components/component-library/button-base/button-base.js +++ b/ui/components/component-library/button-base/button-base.js @@ -4,7 +4,7 @@ import classnames from 'classnames'; import Box from '../../ui/box'; import { IconName, Icon, IconSize } from '../icon'; -import { Text } from '../text'; +import { Text } from '../text/deprecated'; import { AlignItems, @@ -133,7 +133,7 @@ ButtonBase.propTypes = { /** * Additional props to pass to the Text component that wraps the button children */ - buttonTextProps: PropTypes.shape(Text.PropTypes), + buttonTextProps: PropTypes.shape(Text.propTypes), /** * The children to be rendered inside the ButtonBase */ @@ -195,7 +195,7 @@ ButtonBase.propTypes = { /** * textProps accepts all the props from Icon */ - textProps: PropTypes.shape(Text.PropTypes), + textProps: PropTypes.shape(Text.propTypes), /** * ButtonBase accepts all the props from Box */ diff --git a/ui/components/component-library/help-text/help-text.js b/ui/components/component-library/help-text/help-text.js index 355106400..fb3d77bd6 100644 --- a/ui/components/component-library/help-text/help-text.js +++ b/ui/components/component-library/help-text/help-text.js @@ -9,7 +9,7 @@ import { SEVERITIES, } from '../../../helpers/constants/design-system'; -import { Text } from '../text'; +import { Text } from '../text/deprecated'; export const HelpText = ({ severity, diff --git a/ui/components/component-library/input/input.js b/ui/components/component-library/input/input.js index 28067ba1b..3a67a6919 100644 --- a/ui/components/component-library/input/input.js +++ b/ui/components/component-library/input/input.js @@ -10,7 +10,7 @@ import { import Box from '../../ui/box'; -import { Text } from '../text'; +import { Text } from '../text/deprecated'; import { INPUT_TYPES } from './input.constants'; diff --git a/ui/components/component-library/label/label.js b/ui/components/component-library/label/label.js index 072dde236..4ad84b79d 100644 --- a/ui/components/component-library/label/label.js +++ b/ui/components/component-library/label/label.js @@ -7,7 +7,7 @@ import { Display, AlignItems, } from '../../../helpers/constants/design-system'; -import { Text } from '../text'; +import { Text } from '../text/deprecated'; export const Label = ({ htmlFor, className, children, ...props }) => ( This Text (fka Typography) component has breaking changes in variant options and the line heights associated to each variant. - Good typography improves readability, legibility and hierarchy of information. +> Contribute to improving the UI consistency of the extension by helping to replace the deprecated `` with ``. [See details](#converting-from-typography-to-text) + ## Props -The `Text` accepts all props below as well as all [Box](/docs/components-ui-box--default-story#props) component props +The `Text` accepts all props below as well as all [Box](/docs/components-componentlibrary-box--docs#props) component props @@ -280,7 +280,8 @@ You can also utilize the `ValidTag` enum from `./text.types` to ensure that you ```jsx -import { Text } from '../../component-library'; +import { Display } from '../../../helpers/constants/design-system'; +import { Text } from '../../component-library' dd div @@ -294,9 +295,12 @@ import { Text } from '../../component-library'; h6 li p -span -strong - +span +strong +ul +label +header + ``` Renders the html: @@ -316,6 +320,11 @@ Renders the html:

p

span strong +
    + ul +
+ +
header
``` @@ -360,10 +369,6 @@ import { Text } from '../../component-library';
``` -### Box Props - -Use any valid box props [Box](/?path=/story/components-ui-box--default-story) component props to the Text component. - ### Class Name Adds an additional class to the `Text` component @@ -376,7 +381,7 @@ The text content of the `Text` component # Converting from `Typography` to `Text` -The `Typography` component has been deprecated in favor of the `Text` component. Below are code examples converting from `Typography` to `Text`. +The `Typography` component has been deprecated in favor of the `Text` component. You can contribute by submitting a PR against [Replace deprecated Typography with Text component](https://github.com/MetaMask/metamask-extension/issues/17670) on GitHub. Below are code examples converting from `Typography` to `Text`. ### Variant @@ -575,7 +580,7 @@ Values using the `TextAlign` object from `./ui/helpers/constants/design-system.j ### Box Props -Box props are now integrated with the `Text` component. Valid box props: [Box](/?path=/story/components-ui-box--default-story) +Box props are now integrated with the `Text` component. Valid Box props: [Box](/docs/components-componentlibrary-box--docs#props) You no longer need to pass these props as an object through `boxProps` diff --git a/ui/components/component-library/text/__snapshots__/text.test.tsx.snap b/ui/components/component-library/text/__snapshots__/text.test.tsx.snap index de0c46263..0fcc7b64c 100644 --- a/ui/components/component-library/text/__snapshots__/text.test.tsx.snap +++ b/ui/components/component-library/text/__snapshots__/text.test.tsx.snap @@ -3,67 +3,67 @@ exports[`Text should render the Text with proper variant class name 1`] = `

display-md

heading-lg

heading-md

heading-sm

body-lg-medium

body-md

body-md-medium

body-md-bold

body-sm

body-sm-medium

body-sm-bold

body-xs

body-xs-medium

diff --git a/ui/components/component-library/text/deprecated/__snapshots__/text.test.js.snap b/ui/components/component-library/text/deprecated/__snapshots__/text.test.tsx.snap similarity index 77% rename from ui/components/component-library/text/deprecated/__snapshots__/text.test.js.snap rename to ui/components/component-library/text/deprecated/__snapshots__/text.test.tsx.snap index f9c068518..de0c46263 100644 --- a/ui/components/component-library/text/deprecated/__snapshots__/text.test.js.snap +++ b/ui/components/component-library/text/deprecated/__snapshots__/text.test.tsx.snap @@ -32,6 +32,11 @@ exports[`Text should render the Text with proper variant class name 1`] = ` > body-md

+

+ body-md-medium +

@@ -42,6 +47,11 @@ exports[`Text should render the Text with proper variant class name 1`] = ` > body-sm

+

+ body-sm-medium +

@@ -52,5 +62,10 @@ exports[`Text should render the Text with proper variant class name 1`] = ` > body-xs

+

+ body-xs-medium +

`; diff --git a/ui/components/component-library/text/deprecated/index.js b/ui/components/component-library/text/deprecated/index.js deleted file mode 100644 index aaac5f028..000000000 --- a/ui/components/component-library/text/deprecated/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export { Text } from './text'; -export { TEXT_DIRECTIONS, INVISIBLE_CHARACTER } from './text.constants'; diff --git a/ui/components/component-library/text/deprecated/index.ts b/ui/components/component-library/text/deprecated/index.ts new file mode 100644 index 000000000..0e4a6d9a9 --- /dev/null +++ b/ui/components/component-library/text/deprecated/index.ts @@ -0,0 +1,3 @@ +export { Text } from './text'; +export { ValidTag, TextDirection, InvisibleCharacter } from './text.types'; +export type { TextProps, ValidTagType } from './text.types'; diff --git a/ui/components/component-library/text/deprecated/text.constants.js b/ui/components/component-library/text/deprecated/text.constants.js deleted file mode 100644 index e59e022f4..000000000 --- a/ui/components/component-library/text/deprecated/text.constants.js +++ /dev/null @@ -1,11 +0,0 @@ -export const TEXT_DIRECTIONS = { - LEFT_TO_RIGHT: 'ltr', - RIGHT_TO_LEFT: 'rtl', - AUTO: 'auto', -}; - -/** - * The INVISIBLE_CHARACTER is a very useful tool if you want to make sure a line of text - * takes up vertical space even if it's empty. - */ -export const INVISIBLE_CHARACTER = '\u200B'; diff --git a/ui/components/component-library/text/deprecated/text.js b/ui/components/component-library/text/deprecated/text.js deleted file mode 100644 index b483661aa..000000000 --- a/ui/components/component-library/text/deprecated/text.js +++ /dev/null @@ -1,185 +0,0 @@ -import React from 'react'; -import classnames from 'classnames'; -import PropTypes from 'prop-types'; -import Box from '../../../ui/box'; -import { - FONT_WEIGHT, - FONT_STYLE, - TextVariant, - TextAlign, - TEXT_TRANSFORM, - OVERFLOW_WRAP, - TextColor, -} from '../../../../helpers/constants/design-system'; -import { TEXT_DIRECTIONS } from './text.constants'; - -export const ValidTags = [ - 'dd', - 'div', - 'dt', - 'em', - 'h1', - 'h2', - 'h3', - 'h4', - 'h5', - 'h6', - 'li', - 'p', - 'span', - 'strong', - 'ul', - 'label', - 'input', -]; - -const getTextElementDefault = (variant) => { - switch (variant) { - case TextVariant.displayMd: - return 'h1'; - case TextVariant.headingLg: - return 'h2'; - case TextVariant.headingMd: - return 'h3'; - case TextVariant.headingSm: - return 'h4'; - case TextVariant.inherit: - return 'span'; - // TextVariant.bodyLgMedium, TextVariant.bodyMd, TextVariant.bodyMdBold, TextVariant.bodySm, TextVariant.bodySmBold, TextVariant.bodyXs use default 'p' tag - default: - return 'p'; - } -}; - -export const Text = React.forwardRef( - ( - { - variant = TextVariant.bodyMd, - color = TextColor.textDefault, - fontWeight, - fontStyle, - textTransform, - textAlign, - textDirection, - overflowWrap, - ellipsis, - as, - className, - children, - ...props - }, - ref, - ) => { - // Check if as is set otherwise set a default tag based on variant - const Tag = as ?? getTextElementDefault(variant); - let strongTagFontWeight; - - if (Tag === 'strong') { - strongTagFontWeight = FONT_WEIGHT.BOLD; - } - - const computedClassName = classnames( - 'mm-text', - className, - `mm-text--${variant}`, - (strongTagFontWeight || fontWeight) && - `mm-text--font-weight-${strongTagFontWeight || fontWeight}`, - { - [`mm-text--font-style-${fontStyle}`]: Boolean(fontStyle), - [`mm-text--ellipsis`]: Boolean(ellipsis), - [`mm-text--text-transform-${textTransform}`]: Boolean(textTransform), - [`mm-text--text-align-${textAlign}`]: Boolean(textAlign), - [`mm-text--overflow-wrap-${overflowWrap}`]: Boolean(overflowWrap), - }, - ); - - return ( - - {children} - - ); - }, -); - -Text.propTypes = { - /** - * The variation of font styles including sizes and weights of the Text component - * Possible values: - * `DISPLAY_MD` large screen: 48px / small screen: 32px, - * `HEADING_LG` large screen: 32px / small screen: 24px, - * `HEADING_MD` large screen: 24px / small screen: 18px, - * `HEADING_SM` large screen: 18px / small screen: 16px, - * `BODY_LG_MEDIUM` large screen: 18px / small screen: 16px, - * `BODY_MD` large screen: 16px / small screen: 14px, - * `BODY_MD_BOLD` large screen: 16px / small screen: 14px, - * `BODY_SM` large screen: 14px / small screen: 12px, - * `BODY_SM_BOLD` large screen: 14px / small screen: 12px, - * `BODY_XS` large screen: 12px / small screen: 10px, - * `INHERIT` - */ - variant: PropTypes.oneOf(Object.values(TextVariant)), - /** - * The color of the Text component Should use the COLOR object from - * ./ui/helpers/constants/design-system.js - */ - color: PropTypes.oneOf(Object.values(TextColor)), - /** - * The font-weight of the Text component. Should use the FONT_WEIGHT object from - * ./ui/helpers/constants/design-system.js - */ - fontWeight: PropTypes.oneOf(Object.values(FONT_WEIGHT)), - /** - * The font-style of the Text component. Should use the FONT_STYLE object from - * ./ui/helpers/constants/design-system.js - */ - fontStyle: PropTypes.oneOf(Object.values(FONT_STYLE)), - /** - * The textTransform of the Text component. Should use the TEXT_TRANSFORM object from - * ./ui/helpers/constants/design-system.js - */ - textTransform: PropTypes.oneOf(Object.values(TEXT_TRANSFORM)), - /** - * The text-align of the Text component. Should use the TextAlign enum from - * ./ui/helpers/constants/design-system.js - */ - textAlign: PropTypes.oneOf(Object.values(TextAlign)), - /** - * Change the dir (direction) global attribute of text to support the direction a language is written - * Possible values: `LEFT_TO_RIGHT` (default), `RIGHT_TO_LEFT`, `AUTO` (user agent decides) - */ - textDirection: PropTypes.oneOf(Object.values(TEXT_DIRECTIONS)), - /** - * The overflow-wrap of the Text component. Should use the OVERFLOW_WRAP object from - * ./ui/helpers/constants/design-system.js - */ - overflowWrap: PropTypes.oneOf(Object.values(OVERFLOW_WRAP)), - /** - * Used for long strings that can be cut off... - */ - ellipsis: PropTypes.bool, - /** - * Changes the root html element tag of the Text component. - */ - as: PropTypes.oneOf(ValidTags), - /** - * Additional className to assign the Text component - */ - className: PropTypes.string, - /** - * The text content of the Text component - */ - children: PropTypes.node.isRequired, - /** - * Text component accepts all Box component props - */ - ...Box.propTypes, -}; - -Text.displayName = 'Text'; // Used for React DevTools profiler diff --git a/ui/components/component-library/text/deprecated/text.test.js b/ui/components/component-library/text/deprecated/text.test.tsx similarity index 86% rename from ui/components/component-library/text/deprecated/text.test.js rename to ui/components/component-library/text/deprecated/text.test.tsx index 2a61e4fe4..4608da9c4 100644 --- a/ui/components/component-library/text/deprecated/text.test.js +++ b/ui/components/component-library/text/deprecated/text.test.tsx @@ -1,16 +1,17 @@ import * as React from 'react'; import { render } from '@testing-library/react'; import { - FONT_STYLE, - FONT_WEIGHT, - OVERFLOW_WRAP, + FontStyle, + FontWeight, + OverflowWrap, TextAlign, TextColor, - TEXT_TRANSFORM, + TextTransform, TextVariant, Color, } from '../../../../helpers/constants/design-system'; -import { Text, TEXT_DIRECTIONS } from '.'; +import { TextDirection } from './text.types'; +import { Text } from '.'; describe('Text', () => { it('should render the Text without crashing', () => { @@ -75,10 +76,13 @@ describe('Text', () => { heading-sm body-lg-medium body-md + body-md-medium body-md-bold body-sm + body-sm-medium body-sm-bold body-xs + body-xs-medium , ); @@ -88,19 +92,22 @@ describe('Text', () => { expect(getByText('heading-sm')).toHaveClass('mm-text--heading-sm'); expect(getByText('body-lg-medium')).toHaveClass('mm-text--body-lg-medium'); expect(getByText('body-md')).toHaveClass('mm-text--body-md'); + expect(getByText('body-md-medium')).toHaveClass('mm-text--body-md-medium'); expect(getByText('body-md-bold')).toHaveClass('mm-text--body-md-bold'); expect(getByText('body-sm')).toHaveClass('mm-text--body-sm'); + expect(getByText('body-sm-medium')).toHaveClass('mm-text--body-sm-medium'); expect(getByText('body-sm-bold')).toHaveClass('mm-text--body-sm-bold'); expect(getByText('body-xs')).toHaveClass('mm-text--body-xs'); + expect(getByText('body-xs-medium')).toHaveClass('mm-text--body-xs-medium'); expect(container).toMatchSnapshot(); }); it('should render the Text with proper font weight class name', () => { const { getByText } = render( <> - bold - medium - normal + bold + medium + normal , ); expect(getByText('bold')).toHaveClass('mm-text--font-weight-bold'); @@ -155,8 +162,8 @@ describe('Text', () => { it('should render the Text with proper font style class name', () => { const { getByText } = render( <> - italic - normal + italic + normal , ); expect(getByText('italic')).toHaveClass('mm-text--font-style-italic'); @@ -184,8 +191,8 @@ describe('Text', () => { it('should render the Text with proper overflow wrap class name', () => { const { getByText } = render( <> - break-word - normal + break-word + normal , ); expect(getByText('break-word')).toHaveClass( @@ -206,9 +213,9 @@ describe('Text', () => { it('should render the Text with proper text transform class name', () => { const { getByText } = render( <> - uppercase - lowercase - capitalize + uppercase + lowercase + capitalize , ); expect(getByText('uppercase')).toHaveClass( @@ -230,9 +237,9 @@ describe('Text', () => { it('should render the Text with proper direction', () => { const { getByText } = render( <> - auto - ltr - rtl + auto + ltr + rtl , ); expect(getByText('auto')).toHaveAttribute('dir', 'auto'); diff --git a/ui/components/component-library/text/deprecated/text.tsx b/ui/components/component-library/text/deprecated/text.tsx new file mode 100644 index 000000000..cc3a551ff --- /dev/null +++ b/ui/components/component-library/text/deprecated/text.tsx @@ -0,0 +1,89 @@ +import React, { forwardRef, Ref } from 'react'; +import classnames from 'classnames'; +import Box from '../../../ui/box'; +import { + FontWeight, + TextVariant, + TextColor, +} from '../../../../helpers/constants/design-system'; +import { TextProps } from './text.types'; + +const getTextElementDefault = (variant: TextVariant) => { + switch (variant) { + case TextVariant.displayMd: + return 'h1'; + case TextVariant.headingLg: + return 'h2'; + case TextVariant.headingMd: + return 'h3'; + case TextVariant.headingSm: + return 'h4'; + case TextVariant.inherit: + return 'span'; + // TextVariant.bodyLgMedium, TextVariant.bodyMd, TextVariant.bodyMdBold, TextVariant.bodySm, TextVariant.bodySmBold, TextVariant.bodyXs use default 'p' tag + default: + return 'p'; + } +}; + +/** + * @deprecated This version of the `` component has been deprecated + * Use `import { Text } from '../../component-library';` instead + */ + +export const Text = forwardRef(function Text( + { + variant = TextVariant.bodyMd, + color = TextColor.textDefault, + fontWeight, + fontStyle, + textTransform, + textAlign, + textDirection, + overflowWrap, + ellipsis, + as, + className = '', + children, + ...props + }: TextProps, + ref: Ref, +) { + // Check if as is set otherwise set a default tag based on variant + const Tag = as ?? getTextElementDefault(variant); + let strongTagFontWeight; + + if (Tag === 'strong') { + strongTagFontWeight = FontWeight.Bold; + } + + const computedClassName = classnames( + 'mm-text', + className, + `mm-text--${variant}`, + { + [`mm-text--font-weight-${strongTagFontWeight || fontWeight}`]: Boolean( + strongTagFontWeight || fontWeight, + ), + [`mm-text--font-style-${String(fontStyle)}`]: Boolean(fontStyle), + [`mm-text--ellipsis`]: Boolean(ellipsis), + [`mm-text--text-transform-${String(textTransform)}`]: + Boolean(textTransform), + [`mm-text--text-align-${String(textAlign)}`]: Boolean(textAlign), + [`mm-text--overflow-wrap-${String(overflowWrap)}`]: Boolean(overflowWrap), + }, + ); + + return ( + + {children} + + ); +}); diff --git a/ui/components/component-library/text/deprecated/text.types.ts b/ui/components/component-library/text/deprecated/text.types.ts new file mode 100644 index 000000000..f6d5debc5 --- /dev/null +++ b/ui/components/component-library/text/deprecated/text.types.ts @@ -0,0 +1,146 @@ +import React from 'react'; +import type { BoxProps } from '../../../ui/box/box.d'; +import { + FontWeight, + FontStyle, + TextVariant, + TextAlign, + TextTransform, + OverflowWrap, + TextColor, + Color, +} from '../../../../helpers/constants/design-system'; + +export enum TextDirection { + LeftToRight = 'ltr', + RightToLeft = 'rtl', + Auto = 'auto', +} + +/** + * The InvisibleCharacter is a very useful tool if you want to make sure a line of text + * takes up vertical space even if it's empty. + */ +export const InvisibleCharacter = '\u200B'; + +/** + * @deprecated ValidTag enum is deprecated in favor of a union of strings. + * To change the root html element tag of the Text component, use the `as` prop and string value. + * e.g. `Hello World` + * + * Contribute to replacing the enum with a union of string by submitting a PR + */ + +export enum ValidTag { + Dd = 'dd', + Div = 'div', + Dt = 'dt', + Em = 'em', + H1 = 'h1', + H2 = 'h2', + H3 = 'h3', + H4 = 'h4', + H5 = 'h5', + H6 = 'h6', + Li = 'li', + P = 'p', + Span = 'span', + Strong = 'strong', + Ul = 'ul', + Label = 'label', + Input = 'input', + Header = 'header', +} + +export type ValidTagType = + | 'dd' + | 'div' + | 'dt' + | 'em' + | 'h1' + | 'h2' + | 'h3' + | 'h4' + | 'h5' + | 'h6' + | 'li' + | 'p' + | 'span' + | 'strong' + | 'ul' + | 'label' + | 'input' + | 'header'; + +export interface TextProps extends BoxProps { + /** + * The text content of the Text component + */ + children?: React.ReactNode; + /** + * The variation of font styles including sizes and weights of the Text component + * Possible values: + * `displayMd` large screen: 48px / small screen: 32px, + * `headingLg` large screen: 32px / small screen: 24px, + * `headingMd` large screen: 24px / small screen: 18px, + * `headingSm` large screen: 18px / small screen: 16px, + * `bodyLgMedium` large screen: 18px / small screen: 16px, + * `bodyMd` large screen: 16px / small screen: 14px, + * `bodyMdMedium` large screen: 16px / small screen: 14px, + * `bodyMdBold` large screen: 16px / small screen: 14px, + * `bodySm` large screen: 14px / small screen: 12px, + * `bodySmMedium` large screen: 14px / small screen: 12px, + * `bodySmBold` large screen: 14px / small screen: 12px, + * `bodyXsMedium` large screen: 12px / small screen: 10px, + * `bodyXs` large screen: 12px / small screen: 10px, + * `inherit` + */ + variant?: TextVariant; + /** + * The color of the Text component Should use the COLOR object from + * ./ui/helpers/constants/design-system.js + */ + color?: TextColor | Color; + /** + * The font-weight of the Text component. Should use the FontWeight enum from + * ./ui/helpers/constants/design-system.js + */ + fontWeight?: FontWeight; + /** + * The font-style of the Text component. Should use the FontStyle enum from + * ./ui/helpers/constants/design-system.js + */ + fontStyle?: FontStyle; + /** + * The textTransform of the Text component. Should use the TextTransform enum from + * ./ui/helpers/constants/design-system.js + */ + textTransform?: TextTransform; + /** + * The text-align of the Text component. Should use the TextAlign enum from + * ./ui/helpers/constants/design-system.js + */ + textAlign?: TextAlign; + /** + * Change the dir (direction) global attribute of text to support the direction a language is written + * Possible values: `LEFT_TO_RIGHT` (default), `RIGHT_TO_LEFT`, `AUTO` (user agent decides) + */ + textDirection?: TextDirection; + /** + * The overflow-wrap of the Text component. Should use the OverflowWrap enum from + * ./ui/helpers/constants/design-system.js + */ + overflowWrap?: OverflowWrap; + /** + * Used for long strings that can be cut off... + */ + ellipsis?: boolean; + /** + * Changes the root html element tag of the Text component. + */ + as?: ValidTagType; + /** + * Additional className to assign the Text component + */ + className?: string; +} diff --git a/ui/components/component-library/text/index.ts b/ui/components/component-library/text/index.ts index 0e4a6d9a9..8ec2cd13f 100644 --- a/ui/components/component-library/text/index.ts +++ b/ui/components/component-library/text/index.ts @@ -1,3 +1,7 @@ export { Text } from './text'; export { ValidTag, TextDirection, InvisibleCharacter } from './text.types'; -export type { TextProps, ValidTagType } from './text.types'; +export type { + TextStyleUtilityProps, + TextProps, + ValidTagType, +} from './text.types'; diff --git a/ui/components/component-library/text/text.scss b/ui/components/component-library/text/text.scss index 2185ea659..46d6f2cc6 100644 --- a/ui/components/component-library/text/text.scss +++ b/ui/components/component-library/text/text.scss @@ -26,13 +26,11 @@ $text-variants: ( } } - - .mm-text { // Set default styles - color: var(--color-text-default); font-family: var(--font-family-sans); + &:is(strong), strong { font-weight: var(--font-weight-bold); } diff --git a/ui/components/component-library/text/text.stories.tsx b/ui/components/component-library/text/text.stories.tsx index 6ec6cbc75..6ddddbe07 100644 --- a/ui/components/component-library/text/text.stories.tsx +++ b/ui/components/component-library/text/text.stories.tsx @@ -16,15 +16,15 @@ import { Color, } from '../../../helpers/constants/design-system'; -import Box from '../../ui/box'; +import { Box } from '..'; + import README from './README.mdx'; import { Text } from './text'; -import { ValidTag, TextDirection } from './text.types'; +import { TextDirection } from './text.types'; export default { title: 'Components/ComponentLibrary/Text', component: Text, - parameters: { docs: { page: README, @@ -198,25 +198,58 @@ export const Ellipsis: StoryFn = (args) => ( export const As: StoryFn = (args) => ( <> - {Object.keys(ValidTag).map((tag) => { - if (ValidTag[tag] === ValidTag.Input) { - return ( - - ); - } - return ( -
- - {ValidTag[tag]} - -
- ); - })} + + dd + + + div + + + dt + + + em + + + h1 + + + h2 + + + h3 + + + h4 + + + h5 + + + h6 + + + li + + + p + + + span + + + strong + + + ul + + + label + + + header + + ); @@ -243,10 +276,10 @@ export const TextDirectionStory: StoryFn = (args) => ( export const Strong: StoryFn = (args) => ( <> - This is an as="strong" demo. + Text as="strong" tag - This is a strong element demo. + This is a strong tag as a child inside of Text ); diff --git a/ui/components/component-library/text/text.test.tsx b/ui/components/component-library/text/text.test.tsx index 2de6ce764..cc6f08cdd 100644 --- a/ui/components/component-library/text/text.test.tsx +++ b/ui/components/component-library/text/text.test.tsx @@ -8,10 +8,9 @@ import { TextColor, TextTransform, TextVariant, - Color, } from '../../../helpers/constants/design-system'; import { TextDirection } from './text.types'; -import { Text } from '.'; +import { Text } from './text'; describe('Text', () => { it('should render the Text without crashing', () => { @@ -121,7 +120,7 @@ describe('Text', () => { text-default text-alternative text-muted - overlay-inverse + overlay-inverse primary-default primary-inverse error-default @@ -133,30 +132,34 @@ describe('Text', () => { info-inverse , ); - expect(getByText('text-default')).toHaveClass('box--color-text-default'); + expect(getByText('text-default')).toHaveClass('mm-box--color-text-default'); expect(getByText('text-alternative')).toHaveClass( - 'box--color-text-alternative', + 'mm-box--color-text-alternative', ); - expect(getByText('text-muted')).toHaveClass('box--color-text-muted'); + expect(getByText('text-muted')).toHaveClass('mm-box--color-text-muted'); expect(getByText('primary-default')).toHaveClass( - 'box--color-primary-default', + 'mm-box--color-primary-default', ); expect(getByText('primary-inverse')).toHaveClass( - 'box--color-primary-inverse', + 'mm-box--color-primary-inverse', + ); + expect(getByText('error-default')).toHaveClass( + 'mm-box--color-error-default', + ); + expect(getByText('error-inverse')).toHaveClass( + 'mm-box--color-error-inverse', ); - expect(getByText('error-default')).toHaveClass('box--color-error-default'); - expect(getByText('error-inverse')).toHaveClass('box--color-error-inverse'); expect(getByText('success-default')).toHaveClass( - 'box--color-success-default', + 'mm-box--color-success-default', ); expect(getByText('success-inverse')).toHaveClass( - 'box--color-success-inverse', + 'mm-box--color-success-inverse', ); expect(getByText('warning-inverse')).toHaveClass( - 'box--color-warning-inverse', + 'mm-box--color-warning-inverse', ); - expect(getByText('info-default')).toHaveClass('box--color-info-default'); - expect(getByText('info-inverse')).toHaveClass('box--color-info-inverse'); + expect(getByText('info-default')).toHaveClass('mm-box--color-info-default'); + expect(getByText('info-inverse')).toHaveClass('mm-box--color-info-inverse'); }); it('should render the Text with proper font style class name', () => { diff --git a/ui/components/component-library/text/text.tsx b/ui/components/component-library/text/text.tsx index 3bd9b423e..25d763433 100644 --- a/ui/components/component-library/text/text.tsx +++ b/ui/components/component-library/text/text.tsx @@ -1,12 +1,16 @@ -import React, { forwardRef, Ref } from 'react'; +import React from 'react'; import classnames from 'classnames'; -import Box from '../../ui/box'; + import { - FontWeight, TextVariant, TextColor, } from '../../../helpers/constants/design-system'; -import { TextProps } from './text.types'; + +import { Box } from '..'; + +import type { PolymorphicRef } from '../box'; + +import { TextProps, TextComponent } from './text.types'; const getTextElementDefault = (variant: TextVariant) => { switch (variant) { @@ -26,59 +30,50 @@ const getTextElementDefault = (variant: TextVariant) => { } }; -export const Text = forwardRef(function Text( - { - variant = TextVariant.bodyMd, - color = TextColor.textDefault, - fontWeight, - fontStyle, - textTransform, - textAlign, - textDirection, - overflowWrap, - ellipsis, - as, - className = '', - children, - ...props - }: TextProps, - ref: Ref, -) { - // Check if as is set otherwise set a default tag based on variant - const Tag = as ?? getTextElementDefault(variant); - let strongTagFontWeight; - - if (Tag === 'strong') { - strongTagFontWeight = FontWeight.Bold; - } - - const computedClassName = classnames( - 'mm-text', - className, - `mm-text--${variant}`, +export const Text: TextComponent = React.forwardRef( + ( { - [`mm-text--font-weight-${strongTagFontWeight || fontWeight}`]: Boolean( - strongTagFontWeight || fontWeight, - ), - [`mm-text--font-style-${String(fontStyle)}`]: Boolean(fontStyle), - [`mm-text--ellipsis`]: Boolean(ellipsis), - [`mm-text--text-transform-${String(textTransform)}`]: - Boolean(textTransform), - [`mm-text--text-align-${String(textAlign)}`]: Boolean(textAlign), - [`mm-text--overflow-wrap-${String(overflowWrap)}`]: Boolean(overflowWrap), - }, - ); - - return ( - - {children} - - ); -}); + variant = TextVariant.bodyMd, + fontWeight, + fontStyle, + textTransform, + textAlign, + textDirection, + overflowWrap, + ellipsis, + className = '', + children, + ...props + }: TextProps, + ref?: PolymorphicRef, + ) => { + // Set tag based on variant + // If as prop is passed tag will be overridden + const tag = getTextElementDefault(variant); + const computedClassName = classnames( + 'mm-text', + className, + `mm-text--${variant}`, + { + [`mm-text--font-weight-${fontWeight}`]: Boolean(fontWeight), + [`mm-text--font-style-${fontStyle}`]: Boolean(fontStyle), + [`mm-text--ellipsis`]: Boolean(ellipsis), + [`mm-text--text-transform-${textTransform}`]: Boolean(textTransform), + [`mm-text--text-align-${textAlign}`]: Boolean(textAlign), + [`mm-text--overflow-wrap-${overflowWrap}`]: Boolean(overflowWrap), + }, + ); + return ( + + {children} + + ); + }, +); diff --git a/ui/components/component-library/text/text.types.ts b/ui/components/component-library/text/text.types.ts index c83a41ce7..2afc5a714 100644 --- a/ui/components/component-library/text/text.types.ts +++ b/ui/components/component-library/text/text.types.ts @@ -1,5 +1,4 @@ import React from 'react'; -import type { BoxProps } from '../../ui/box/box.d'; import { FontWeight, FontStyle, @@ -7,10 +6,13 @@ import { TextAlign, TextTransform, OverflowWrap, - TextColor, - Color, } from '../../../helpers/constants/design-system'; +import type { + StyleUtilityProps, + PolymorphicComponentPropWithRef, +} from '../box'; + export enum TextDirection { LeftToRight = 'ltr', RightToLeft = 'rtl', @@ -72,7 +74,11 @@ export type ValidTagType = | 'input' | 'header'; -export interface TextProps extends BoxProps { +export interface TextStyleUtilityProps extends StyleUtilityProps { + /** + * Additional className to assign the Text component + */ + className?: string; /** * The text content of the Text component */ @@ -96,11 +102,6 @@ export interface TextProps extends BoxProps { * `inherit` */ variant?: TextVariant; - /** - * The color of the Text component Should use the COLOR object from - * ./ui/helpers/constants/design-system.js - */ - color?: TextColor | Color; /** * The font-weight of the Text component. Should use the FontWeight enum from * ./ui/helpers/constants/design-system.js @@ -135,12 +136,11 @@ export interface TextProps extends BoxProps { * Used for long strings that can be cut off... */ ellipsis?: boolean; - /** - * Changes the root html element tag of the Text component. - */ - as?: ValidTagType; - /** - * Additional className to assign the Text component - */ - className?: string; } + +export type TextProps = + PolymorphicComponentPropWithRef; + +export type TextComponent = ( + props: TextProps, +) => React.ReactElement | null; diff --git a/ui/components/institutional/compliance-details/compliance-details.js b/ui/components/institutional/compliance-details/compliance-details.js index 65c98b825..58ec06c89 100644 --- a/ui/components/institutional/compliance-details/compliance-details.js +++ b/ui/components/institutional/compliance-details/compliance-details.js @@ -11,7 +11,8 @@ import { getComplianceTenantSubdomain, } from '../../../ducks/institutional/institutional'; import { formatDate } from '../../../helpers/utils/util'; -import { Text, Box } from '../../component-library'; +import { Box } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { TextColor, TextVariant, diff --git a/ui/components/institutional/compliance-modal/compliance-modal.js b/ui/components/institutional/compliance-modal/compliance-modal.js index 5bf2f2497..5c3805c56 100644 --- a/ui/components/institutional/compliance-modal/compliance-modal.js +++ b/ui/components/institutional/compliance-modal/compliance-modal.js @@ -4,7 +4,8 @@ import { useI18nContext } from '../../../hooks/useI18nContext'; import { hideModal } from '../../../store/actions'; import Modal from '../../app/modal'; import Box from '../../ui/box'; -import { Text, ButtonIcon, IconSize, IconName } from '../../component-library'; +import { ButtonIcon, IconSize, IconName } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { AlignItems, JustifyContent, diff --git a/ui/components/institutional/compliance-settings/compliance-settings.js b/ui/components/institutional/compliance-settings/compliance-settings.js index 73aa65401..4c1223252 100644 --- a/ui/components/institutional/compliance-settings/compliance-settings.js +++ b/ui/components/institutional/compliance-settings/compliance-settings.js @@ -11,12 +11,8 @@ import { } from '../../../helpers/constants/design-system'; import { I18nContext } from '../../../contexts/i18n'; import { mmiActionsFactory } from '../../../store/institutional/institution-background'; -import { - Text, - Button, - BUTTON_VARIANT, - BUTTON_SIZES, -} from '../../component-library'; +import { Button, BUTTON_VARIANT, BUTTON_SIZES } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import Box from '../../ui/box'; const ComplianceSettings = () => { diff --git a/ui/components/institutional/confirm-remove-jwt-modal/confirm-remove-jwt-modal.js b/ui/components/institutional/confirm-remove-jwt-modal/confirm-remove-jwt-modal.js index f8dd64715..1f82c384a 100644 --- a/ui/components/institutional/confirm-remove-jwt-modal/confirm-remove-jwt-modal.js +++ b/ui/components/institutional/confirm-remove-jwt-modal/confirm-remove-jwt-modal.js @@ -6,7 +6,7 @@ import CustodyAccountList from '../../../pages/institutional/connect-custody/acc import { useI18nContext } from '../../../hooks/useI18nContext'; import { removeAccount } from '../../../store/actions'; import withModalProps from '../../../helpers/higher-order-components/with-modal-props'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import Box from '../../ui/box'; import { BorderRadius, diff --git a/ui/components/institutional/custody-confirm-link-modal/custody-confirm-link-modal.js b/ui/components/institutional/custody-confirm-link-modal/custody-confirm-link-modal.js index 36e1ef821..f98b16dda 100644 --- a/ui/components/institutional/custody-confirm-link-modal/custody-confirm-link-modal.js +++ b/ui/components/institutional/custody-confirm-link-modal/custody-confirm-link-modal.js @@ -27,7 +27,8 @@ import { TextColor, TextVariant, } from '../../../helpers/constants/design-system'; -import { Text, Button, BUTTON_VARIANT } from '../../component-library'; +import { Button, BUTTON_VARIANT } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; const CustodyConfirmLink = () => { const t = useI18nContext(); diff --git a/ui/components/institutional/custody-labels/custody-labels.js b/ui/components/institutional/custody-labels/custody-labels.js index b095e5f3e..3044d0f9a 100644 --- a/ui/components/institutional/custody-labels/custody-labels.js +++ b/ui/components/institutional/custody-labels/custody-labels.js @@ -1,6 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { Text, Label } from '../../component-library'; +import { Label } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { TextTransform, BackgroundColor, diff --git a/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.js b/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.js index 232f4817f..d9e1e98ce 100644 --- a/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.js +++ b/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.js @@ -12,8 +12,8 @@ import { ModalContent, ModalHeader, ModalOverlay, - Text, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { BlockSize, diff --git a/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.js b/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.js index 813a55662..4a17f7c77 100644 --- a/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.js +++ b/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.js @@ -24,9 +24,9 @@ import { IconName, IconSize, ButtonLink, - Text, Box, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; const InteractiveReplacementTokenNotification = ({ isVisible }) => { const t = useI18nContext(); diff --git a/ui/components/institutional/jwt-dropdown/jwt-dropdown.js b/ui/components/institutional/jwt-dropdown/jwt-dropdown.js index 118f522e7..5e43e163f 100644 --- a/ui/components/institutional/jwt-dropdown/jwt-dropdown.js +++ b/ui/components/institutional/jwt-dropdown/jwt-dropdown.js @@ -2,7 +2,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import Dropdown from '../../ui/dropdown'; import { Color } from '../../../helpers/constants/design-system'; -import { Box, Text } from '../../component-library'; +import { Box } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { useI18nContext } from '../../../hooks/useI18nContext'; const JwtDropdown = (props) => { diff --git a/ui/components/institutional/jwt-url-form/jwt-url-form.js b/ui/components/institutional/jwt-url-form/jwt-url-form.js index 5ddf29ac1..867e32095 100644 --- a/ui/components/institutional/jwt-url-form/jwt-url-form.js +++ b/ui/components/institutional/jwt-url-form/jwt-url-form.js @@ -8,7 +8,8 @@ import { FlexDirection, TextVariant, } from '../../../helpers/constants/design-system'; -import { Box, Button, Text } from '../../component-library'; +import { Box, Button } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import JwtDropdown from '../jwt-dropdown'; const JwtUrlForm = (props) => { diff --git a/ui/components/institutional/note-to-trader/note-to-trader.js b/ui/components/institutional/note-to-trader/note-to-trader.js index d4aa601c0..019fa0862 100644 --- a/ui/components/institutional/note-to-trader/note-to-trader.js +++ b/ui/components/institutional/note-to-trader/note-to-trader.js @@ -5,7 +5,8 @@ import { FlexDirection, JustifyContent, } from '../../../helpers/constants/design-system'; -import { Label, Text } from '../../component-library'; +import { Label } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import Box from '../../ui/box'; const NoteToTrader = (props) => { diff --git a/ui/components/institutional/transaction-failed-modal/transaction-failed.js b/ui/components/institutional/transaction-failed-modal/transaction-failed.js index c594c8097..8c4188794 100644 --- a/ui/components/institutional/transaction-failed-modal/transaction-failed.js +++ b/ui/components/institutional/transaction-failed-modal/transaction-failed.js @@ -13,7 +13,8 @@ import { TextAlign, TextVariant, } from '../../../helpers/constants/design-system'; -import { Text, Icon, IconName, IconSize } from '../../component-library'; +import { Icon, IconName, IconSize } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; const TransactionFailedModal = ({ hideModal, diff --git a/ui/components/institutional/wrong-network-notification/wrong-network-notification.js b/ui/components/institutional/wrong-network-notification/wrong-network-notification.js index 3fecdb764..b260e84dc 100644 --- a/ui/components/institutional/wrong-network-notification/wrong-network-notification.js +++ b/ui/components/institutional/wrong-network-notification/wrong-network-notification.js @@ -12,7 +12,8 @@ import { getSelectedAccountCachedBalance } from '../../../selectors'; import { getIsCustodianSupportedChain } from '../../../selectors/institutional/selectors'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { getProviderConfig } from '../../../ducks/metamask/metamask'; -import { Text, Icon, IconName, IconSize } from '../../component-library'; +import { Icon, IconName, IconSize } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import Box from '../../ui/box'; const WrongNetworkNotification = () => { diff --git a/ui/components/multichain/account-details/account-details-authenticate.js b/ui/components/multichain/account-details/account-details-authenticate.js index ba0b1236b..d0deb1203 100644 --- a/ui/components/multichain/account-details/account-details-authenticate.js +++ b/ui/components/multichain/account-details/account-details-authenticate.js @@ -12,9 +12,9 @@ import { ButtonPrimary, ButtonSecondary, FormTextField, - Text, Box, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { exportAccount, hideWarning } from '../../../store/actions'; diff --git a/ui/components/multichain/account-details/account-details-key.js b/ui/components/multichain/account-details/account-details-key.js index 50e3517b1..cc46a474c 100644 --- a/ui/components/multichain/account-details/account-details-key.js +++ b/ui/components/multichain/account-details/account-details-key.js @@ -5,9 +5,9 @@ import { ButtonIcon, ButtonPrimary, IconName, - Text, Box, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { AlignItems, BorderColor, diff --git a/ui/components/multichain/account-details/account-details.js b/ui/components/multichain/account-details/account-details.js index 2921b0db0..d8bb25339 100644 --- a/ui/components/multichain/account-details/account-details.js +++ b/ui/components/multichain/account-details/account-details.js @@ -14,9 +14,9 @@ import { ModalContent, ModalHeader, ModalOverlay, - Text, Box, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { getMetaMaskAccountsOrdered } from '../../../selectors'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { diff --git a/ui/components/multichain/account-list-item-menu/account-list-item-menu.js b/ui/components/multichain/account-list-item-menu/account-list-item-menu.js index cb763097d..ec69a70be 100644 --- a/ui/components/multichain/account-list-item-menu/account-list-item-menu.js +++ b/ui/components/multichain/account-list-item-menu/account-list-item-menu.js @@ -25,13 +25,13 @@ import { findKeyringForAddress } from '../../../ducks/metamask/metamask'; import { NETWORKS_ROUTE } from '../../../helpers/constants/routes'; import { MenuItem } from '../../ui/menu'; import { - Text, IconName, Popover, PopoverPosition, ModalFocus, PopoverRole, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { MetaMetricsEventCategory, MetaMetricsEventLinkType, 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 5066578fd..6fbfa876e 100644 --- a/ui/components/multichain/account-list-item/account-list-item.js +++ b/ui/components/multichain/account-list-item/account-list-item.js @@ -11,7 +11,6 @@ import { AccountListItemMenu } from '..'; import { AvatarAccount, Box, - Text, AvatarFavicon, Tag, ButtonLink, @@ -20,6 +19,7 @@ import { IconSize, AvatarAccountVariant, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { Color, TextAlign, diff --git a/ui/components/multichain/account-list-menu/account-list-menu.js b/ui/components/multichain/account-list-menu/account-list-menu.js index 52f17dba6..03513f477 100644 --- a/ui/components/multichain/account-list-menu/account-list-menu.js +++ b/ui/components/multichain/account-list-menu/account-list-menu.js @@ -7,13 +7,13 @@ import { IconName, ButtonLink, TextFieldSearch, - Text, Box, Modal, ModalContent, ModalOverlay, ModalHeader, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { AccountListItem, CreateAccount, ImportAccount } from '..'; import { BlockSize, diff --git a/ui/components/multichain/account-picker/account-picker.js b/ui/components/multichain/account-picker/account-picker.js index 8ac99e61e..a3986ad36 100644 --- a/ui/components/multichain/account-picker/account-picker.js +++ b/ui/components/multichain/account-picker/account-picker.js @@ -7,8 +7,8 @@ import { AvatarAccountVariant, Icon, IconName, - Text, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { AlignItems, BackgroundColor, diff --git a/ui/components/multichain/global-menu/global-menu.js b/ui/components/multichain/global-menu/global-menu.js index 50ff45780..d67107a67 100644 --- a/ui/components/multichain/global-menu/global-menu.js +++ b/ui/components/multichain/global-menu/global-menu.js @@ -12,12 +12,10 @@ import { } from '../../../helpers/constants/routes'; import { lockMetamask } from '../../../store/actions'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import { - IconName, - ///: BEGIN:ONLY_INCLUDE_IN(snaps) - Text, - ///: END:ONLY_INCLUDE_IN(snaps) -} from '../../component-library'; +import { IconName } from '../../component-library'; +///: BEGIN:ONLY_INCLUDE_IN(snaps) +import { Text } from '../../component-library/text/deprecated'; +///: END:ONLY_INCLUDE_IN(snaps) import { Menu, MenuItem } from '../../ui/menu'; import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../shared/constants/app'; diff --git a/ui/components/multichain/import-account/import-account.js b/ui/components/multichain/import-account/import-account.js index ea5f61b32..e07b31826 100644 --- a/ui/components/multichain/import-account/import-account.js +++ b/ui/components/multichain/import-account/import-account.js @@ -7,7 +7,8 @@ import { MetaMetricsEventCategory, MetaMetricsEventName, } from '../../../../shared/constants/metametrics'; -import { ButtonLink, Label, Text, Box } from '../../component-library'; +import { ButtonLink, Label, Box } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import Dropdown from '../../ui/dropdown'; import { MetaMetricsContext } from '../../../contexts/metametrics'; import { diff --git a/ui/components/multichain/import-account/json.js b/ui/components/multichain/import-account/json.js index ac14d45de..af768103f 100644 --- a/ui/components/multichain/import-account/json.js +++ b/ui/components/multichain/import-account/json.js @@ -5,10 +5,10 @@ import FileInput from 'react-simple-file-input'; import { ButtonLink, FormTextField, - Text, TEXT_FIELD_SIZES, TEXT_FIELD_TYPES, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { Size, TextVariant, diff --git a/ui/components/multichain/network-list-menu/network-list-menu.js b/ui/components/multichain/network-list-menu/network-list-menu.js index 0006a332e..3569e21f7 100644 --- a/ui/components/multichain/network-list-menu/network-list-menu.js +++ b/ui/components/multichain/network-list-menu/network-list-menu.js @@ -30,9 +30,9 @@ import { ModalContent, ModalHeader, ModalOverlay, - Text, Box, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { ADD_POPULAR_CUSTOM_NETWORK } from '../../../helpers/constants/routes'; import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../shared/constants/app'; diff --git a/ui/components/multichain/product-tour-popover/product-tour-popover.js b/ui/components/multichain/product-tour-popover/product-tour-popover.js index d782bc44c..11b683fdd 100644 --- a/ui/components/multichain/product-tour-popover/product-tour-popover.js +++ b/ui/components/multichain/product-tour-popover/product-tour-popover.js @@ -14,13 +14,8 @@ import { TextVariant, TextAlign, } from '../../../helpers/constants/design-system'; -import { - ButtonBase, - ButtonIcon, - IconName, - Text, - Box, -} from '../../component-library'; +import { ButtonBase, ButtonIcon, IconName, Box } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { Menu } from '../../ui/menu'; diff --git a/ui/components/multichain/token-list-item/token-list-item.js b/ui/components/multichain/token-list-item/token-list-item.js index d305660c9..4ddb40dcd 100644 --- a/ui/components/multichain/token-list-item/token-list-item.js +++ b/ui/components/multichain/token-list-item/token-list-item.js @@ -18,9 +18,9 @@ import { AvatarNetwork, AvatarToken, BadgeWrapper, - Text, Box, } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { getCurrentChainId, getCurrentNetwork, diff --git a/ui/components/ui/box/box.stories.tsx b/ui/components/ui/box/box.stories.tsx index 1491ae6e2..1450fce89 100644 --- a/ui/components/ui/box/box.stories.tsx +++ b/ui/components/ui/box/box.stories.tsx @@ -16,7 +16,7 @@ import { FlexWrap, } from '../../../helpers/constants/design-system'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import Box from './box'; diff --git a/ui/components/ui/callout/callout.js b/ui/components/ui/callout/callout.js index c2a8f671d..6010129ed 100644 --- a/ui/components/ui/callout/callout.js +++ b/ui/components/ui/callout/callout.js @@ -4,7 +4,8 @@ import classnames from 'classnames'; import InfoIconInverted from '../icon/info-icon-inverted.component'; import { Severity, TextColor } from '../../../helpers/constants/design-system'; import { MILLISECOND } from '../../../../shared/constants/time'; -import { ButtonIcon, IconName, IconSize, Text } from '../../component-library'; +import { ButtonIcon, IconName, IconSize } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; /** * @deprecated `` has been deprecated in favor of the `` diff --git a/ui/components/ui/callout/callout.stories.js b/ui/components/ui/callout/callout.stories.js index 505533bc3..386ae05bf 100644 --- a/ui/components/ui/callout/callout.stories.js +++ b/ui/components/ui/callout/callout.stories.js @@ -5,7 +5,7 @@ import { TextVariant, } from '../../../helpers/constants/design-system'; import Box from '../box'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import Callout from './callout'; export default { diff --git a/ui/components/ui/deprecated-test-networks/deprecated-test-networks.js b/ui/components/ui/deprecated-test-networks/deprecated-test-networks.js index 1c8aaa180..a2107f342 100644 --- a/ui/components/ui/deprecated-test-networks/deprecated-test-networks.js +++ b/ui/components/ui/deprecated-test-networks/deprecated-test-networks.js @@ -12,7 +12,8 @@ import Box from '../box/box'; import ActionableMessage from '../actionable-message/actionable-message'; import { getCurrentChainId } from '../../../selectors'; import { getCompletedOnboarding } from '../../../ducks/metamask/metamask'; -import { Text, Icon, IconName, IconSize } from '../../component-library'; +import { Icon, IconName, IconSize } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; export default function DeprecatedTestNetworks() { const currentChainID = useSelector(getCurrentChainId); diff --git a/ui/components/ui/editable-label/editable-label.js b/ui/components/ui/editable-label/editable-label.js index 8e944efec..651897afa 100644 --- a/ui/components/ui/editable-label/editable-label.js +++ b/ui/components/ui/editable-label/editable-label.js @@ -8,12 +8,8 @@ import { TextVariant, } from '../../../helpers/constants/design-system'; import { getAccountNameErrorMessage } from '../../../helpers/utils/accounts'; -import { - ButtonIcon, - FormTextField, - IconName, - Text, -} from '../../component-library'; +import { ButtonIcon, FormTextField, IconName } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import Box from '../box/box'; export default class EditableLabel extends Component { diff --git a/ui/components/ui/export-text-container/export-text-container.component.js b/ui/components/ui/export-text-container/export-text-container.component.js index e1a51bc69..85f1f1943 100644 --- a/ui/components/ui/export-text-container/export-text-container.component.js +++ b/ui/components/ui/export-text-container/export-text-container.component.js @@ -12,7 +12,8 @@ import { TextVariant, } from '../../../helpers/constants/design-system'; import Box from '../box/box'; -import { ButtonSecondary, Text } from '../../component-library'; +import { ButtonSecondary } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; function ExportTextContainer({ text = '', onClickCopy = null }) { const ONE_MINUTE = 1000 * 60; diff --git a/ui/components/ui/form-field/form-field.js b/ui/components/ui/form-field/form-field.js index 877de5b52..ba522fa4b 100644 --- a/ui/components/ui/form-field/form-field.js +++ b/ui/components/ui/form-field/form-field.js @@ -12,7 +12,8 @@ import { import NumericInput from '../numeric-input/numeric-input.component'; import InfoTooltip from '../info-tooltip/info-tooltip'; -import { Text, Box } from '../../component-library'; +import { Box } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; /** * @deprecated The `` component has been deprecated in favor of the new `` component from the component-library. diff --git a/ui/components/ui/form-field/form-field.stories.js b/ui/components/ui/form-field/form-field.stories.js index 16022af64..1a4f6bc9d 100644 --- a/ui/components/ui/form-field/form-field.stories.js +++ b/ui/components/ui/form-field/form-field.stories.js @@ -3,7 +3,8 @@ import React, { useState } from 'react'; import Tooltip from '../tooltip'; -import { Icon, IconName, Text } from '../../component-library'; +import { Icon, IconName } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { AlignItems } from '../../../helpers/constants/design-system'; import README from './README.mdx'; import FormField from '.'; diff --git a/ui/components/ui/icon-button/icon-button.js b/ui/components/ui/icon-button/icon-button.js index cc95d8343..1e4acfffe 100644 --- a/ui/components/ui/icon-button/icon-button.js +++ b/ui/components/ui/icon-button/icon-button.js @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { TextVariant } from '../../../helpers/constants/design-system'; import Tooltip from '../tooltip/tooltip'; diff --git a/ui/components/ui/logo/logo.stories.js b/ui/components/ui/logo/logo.stories.js index 592d43c8e..802ac739a 100644 --- a/ui/components/ui/logo/logo.stories.js +++ b/ui/components/ui/logo/logo.stories.js @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import { BackgroundColor } from '../../../helpers/constants/design-system'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import Card from '../card'; import Box from '../box'; diff --git a/ui/components/ui/menu/menu-item.js b/ui/components/ui/menu/menu-item.js index 10fcce629..a22d1ad48 100644 --- a/ui/components/ui/menu/menu-item.js +++ b/ui/components/ui/menu/menu-item.js @@ -2,7 +2,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -import { Text, Icon, IconSize } from '../../component-library'; +import { Icon, IconSize } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { TextVariant } from '../../../helpers/constants/design-system'; const MenuItem = React.forwardRef( diff --git a/ui/components/ui/metafox-logo/metafox-logo.stories.js b/ui/components/ui/metafox-logo/metafox-logo.stories.js index 859954144..f059e822a 100644 --- a/ui/components/ui/metafox-logo/metafox-logo.stories.js +++ b/ui/components/ui/metafox-logo/metafox-logo.stories.js @@ -1,6 +1,6 @@ import React from 'react'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import MetaFoxLogo from '.'; export default { diff --git a/ui/components/ui/new-network-info/new-network-info.js b/ui/components/ui/new-network-info/new-network-info.js index 0d449c443..778955dc3 100644 --- a/ui/components/ui/new-network-info/new-network-info.js +++ b/ui/components/ui/new-network-info/new-network-info.js @@ -25,7 +25,8 @@ import { IMPORT_TOKEN_ROUTE } from '../../../helpers/constants/routes'; import Chip from '../chip/chip'; import { setFirstTimeUsedNetwork } from '../../../store/actions'; import { NETWORK_TYPES } from '../../../../shared/constants/network'; -import { Icon, IconName, Text } from '../../component-library'; +import { Icon, IconName } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { getNetworkLabelKey } from '../../../helpers/utils/i18n-helper'; const NewNetworkInfo = () => { diff --git a/ui/components/ui/nft-info/nft-info.js b/ui/components/ui/nft-info/nft-info.js index 60101b487..7e04db323 100644 --- a/ui/components/ui/nft-info/nft-info.js +++ b/ui/components/ui/nft-info/nft-info.js @@ -10,7 +10,7 @@ import { } from '../../../helpers/constants/design-system'; import Identicon from '../identicon'; import Button from '../button'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; export default function NftInfo({ assetName, tokenAddress, tokenId }) { const t = useContext(I18nContext); diff --git a/ui/components/ui/numeric-input/numeric-input.component.js b/ui/components/ui/numeric-input/numeric-input.component.js index 8eba851be..9ae1756d8 100644 --- a/ui/components/ui/numeric-input/numeric-input.component.js +++ b/ui/components/ui/numeric-input/numeric-input.component.js @@ -6,7 +6,7 @@ import { TextVariant, } from '../../../helpers/constants/design-system'; import { DECIMAL_REGEX } from '../../../../shared/constants/tokens'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; export default function NumericInput({ detailText = '', diff --git a/ui/components/ui/popover/popover.component.js b/ui/components/ui/popover/popover.component.js index 261883c56..51c32f715 100644 --- a/ui/components/ui/popover/popover.component.js +++ b/ui/components/ui/popover/popover.component.js @@ -19,13 +19,8 @@ import { BLOCK_SIZES, } from '../../../helpers/constants/design-system'; -import { - ButtonIcon, - Icon, - IconName, - IconSize, - Text, -} from '../../component-library'; +import { ButtonIcon, Icon, IconName, IconSize } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; const defaultHeaderProps = { padding: [6, 4, 4], diff --git a/ui/components/ui/radio-group/radio-group.component.js b/ui/components/ui/radio-group/radio-group.component.js index 3a4b4329d..c63e199d1 100644 --- a/ui/components/ui/radio-group/radio-group.component.js +++ b/ui/components/ui/radio-group/radio-group.component.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import classNames from 'classnames'; import { I18nContext } from '../../../contexts/i18n'; import { Color, TextVariant } from '../../../helpers/constants/design-system'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; function Connector({ isFirst, isLast }) { if (isFirst) { diff --git a/ui/components/ui/review-spending-cap/review-spending-cap.js b/ui/components/ui/review-spending-cap/review-spending-cap.js index d90471317..c6e700bae 100644 --- a/ui/components/ui/review-spending-cap/review-spending-cap.js +++ b/ui/components/ui/review-spending-cap/review-spending-cap.js @@ -3,13 +3,8 @@ import PropTypes from 'prop-types'; import { I18nContext } from '../../../contexts/i18n'; import Box from '../box'; import Tooltip from '../tooltip'; -import { - ButtonLink, - Icon, - IconName, - IconSize, - Text, -} from '../../component-library'; +import { ButtonLink, Icon, IconName, IconSize } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; import { AlignItems, DISPLAY, diff --git a/ui/components/ui/slider/slider.component.js b/ui/components/ui/slider/slider.component.js index 581665062..4bb101809 100644 --- a/ui/components/ui/slider/slider.component.js +++ b/ui/components/ui/slider/slider.component.js @@ -9,7 +9,7 @@ import { } from '../../../helpers/constants/design-system'; import InfoTooltip from '../info-tooltip/info-tooltip'; -import { Text } from '../../component-library'; +import { Text } from '../../component-library/text/deprecated'; const styles = { root: { diff --git a/ui/components/ui/tabs/snaps/dropdown-tab/dropdown-tab.js b/ui/components/ui/tabs/snaps/dropdown-tab/dropdown-tab.js index bbb48602c..6b8f26e84 100644 --- a/ui/components/ui/tabs/snaps/dropdown-tab/dropdown-tab.js +++ b/ui/components/ui/tabs/snaps/dropdown-tab/dropdown-tab.js @@ -14,7 +14,8 @@ import { FLEX_WRAP, TextVariant, } from '../../../../../helpers/constants/design-system'; -import { Icon, IconName, IconSize, Text } from '../../../../component-library'; +import { Icon, IconName, IconSize } from '../../../../component-library'; +import { Text } from '../../../../component-library/text/deprecated'; export const DropdownTab = ({ activeClassName, diff --git a/ui/components/ui/tooltip/tooltip.stories.js b/ui/components/ui/tooltip/tooltip.stories.js index 9eb054443..f17b78f2b 100644 --- a/ui/components/ui/tooltip/tooltip.stories.js +++ b/ui/components/ui/tooltip/tooltip.stories.js @@ -6,7 +6,6 @@ import Tooltip from '.'; export default { title: 'Components/UI/Tooltip', - argTypes: { containerClassName: { control: 'text', diff --git a/ui/helpers/utils/accounts.js b/ui/helpers/utils/accounts.js index cb974f1c6..74a23ce34 100644 --- a/ui/helpers/utils/accounts.js +++ b/ui/helpers/utils/accounts.js @@ -1,4 +1,4 @@ -import { INVISIBLE_CHARACTER } from '../../components/component-library/text/deprecated'; +import { InvisibleCharacter } from '../../components/component-library'; export function getAccountNameErrorMessage( accounts, @@ -30,7 +30,7 @@ export function getAccountNameErrorMessage( let errorMessage; if (isValidAccountName) { - errorMessage = INVISIBLE_CHARACTER; // Using an invisible character, so the spacing stays constant + errorMessage = InvisibleCharacter; // Using an invisible character, so the spacing stays constant } else if (isDuplicateAccountName) { errorMessage = context.t('accountNameDuplicate'); } else if (isReservedAccountName) { diff --git a/ui/helpers/utils/permission.js b/ui/helpers/utils/permission.js index 34e01ee7b..0efb8b49c 100644 --- a/ui/helpers/utils/permission.js +++ b/ui/helpers/utils/permission.js @@ -17,13 +17,13 @@ import Tooltip from '../../components/ui/tooltip'; import { AvatarIcon, ///: BEGIN:ONLY_INCLUDE_IN(snaps) - Text, Icon, ///: END:ONLY_INCLUDE_IN IconName, IconSize, } from '../../components/component-library'; ///: BEGIN:ONLY_INCLUDE_IN(snaps) +import { Text } from '../../components/component-library/text/deprecated'; import { Color, FontWeight, IconColor } from '../constants/design-system'; import { coinTypeToProtocolName, diff --git a/ui/pages/confirm-add-suggested-nft/confirm-add-suggested-nft.js b/ui/pages/confirm-add-suggested-nft/confirm-add-suggested-nft.js index 309a14b39..f74dd27e9 100644 --- a/ui/pages/confirm-add-suggested-nft/confirm-add-suggested-nft.js +++ b/ui/pages/confirm-add-suggested-nft/confirm-add-suggested-nft.js @@ -24,9 +24,9 @@ import { ButtonIconSize, ButtonLink, IconName, - Text, Box, } from '../../components/component-library'; +import { Text } from '../../components/component-library/text/deprecated'; import { getCurrentChainId, getRpcPrefsForCurrentProvider, diff --git a/ui/pages/confirm-approve/confirm-approve-content/__snapshots__/confirm-approve-content.component.test.js.snap b/ui/pages/confirm-approve/confirm-approve-content/__snapshots__/confirm-approve-content.component.test.js.snap index 3512ff69b..eb21729f2 100644 --- a/ui/pages/confirm-approve/confirm-approve-content/__snapshots__/confirm-approve-content.component.test.js.snap +++ b/ui/pages/confirm-approve/confirm-approve-content/__snapshots__/confirm-approve-content.component.test.js.snap @@ -135,7 +135,7 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr class="mm-box custom-nonce__header mm-box--display-inline-flex mm-box--justify-content-flex-start mm-box--align-items-center" >
Nonce
@@ -146,7 +146,7 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr
2
@@ -320,7 +320,7 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr class="mm-box custom-nonce__header mm-box--display-inline-flex mm-box--justify-content-flex-start mm-box--align-items-center" >
Nonce
@@ -331,7 +331,7 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr
2
@@ -505,7 +505,7 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr class="mm-box custom-nonce__header mm-box--display-inline-flex mm-box--justify-content-flex-start mm-box--align-items-center" >
Nonce
@@ -516,7 +516,7 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr
2
@@ -690,7 +690,7 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr class="mm-box custom-nonce__header mm-box--display-inline-flex mm-box--justify-content-flex-start mm-box--align-items-center" >
Nonce
@@ -701,7 +701,7 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr
2
diff --git a/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js b/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js index b25933c8b..3a81f204c 100644 --- a/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js +++ b/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js @@ -31,8 +31,8 @@ import { ButtonIcon, Icon, IconName, - Text, } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import TransactionDetailItem from '../../../components/app/transaction-detail-item/transaction-detail-item.component'; import UserPreferencedCurrencyDisplay from '../../../components/app/user-preferenced-currency-display'; import { PRIMARY, SECONDARY } from '../../../helpers/constants/common'; diff --git a/ui/pages/confirm-deploy-contract/confirm-deploy-contract.component.js b/ui/pages/confirm-deploy-contract/confirm-deploy-contract.component.js index 6c663db0b..840f5b8ac 100644 --- a/ui/pages/confirm-deploy-contract/confirm-deploy-contract.component.js +++ b/ui/pages/confirm-deploy-contract/confirm-deploy-contract.component.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import ConfirmTransactionBase from '../confirm-transaction-base'; import { toBuffer } from '../../../shared/modules/buffer-utils'; import Box from '../../components/ui/box'; -import { Text } from '../../components/component-library'; +import { Text } from '../../components/component-library/text/deprecated'; import { Color, DISPLAY, diff --git a/ui/pages/create-account/connect-hardware/index.js b/ui/pages/create-account/connect-hardware/index.js index 717192998..b93a8671b 100644 --- a/ui/pages/create-account/connect-hardware/index.js +++ b/ui/pages/create-account/connect-hardware/index.js @@ -24,8 +24,8 @@ import { BUTTON_VARIANT, BUTTON_SIZES, Button, - Text, } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import ZENDESK_URLS from '../../../helpers/constants/zendesk-url'; import { TextColor } from '../../../helpers/constants/design-system'; import SelectHardware from './select-hardware'; diff --git a/ui/pages/desktop-pairing/desktop-pairing.component.js b/ui/pages/desktop-pairing/desktop-pairing.component.js index c529aa261..fb42e1d54 100644 --- a/ui/pages/desktop-pairing/desktop-pairing.component.js +++ b/ui/pages/desktop-pairing/desktop-pairing.component.js @@ -16,7 +16,8 @@ import { import Box from '../../components/ui/box/box'; import { useCopyToClipboard } from '../../hooks/useCopyToClipboard'; import Tooltip from '../../components/ui/tooltip'; -import { Text, Button } from '../../components/component-library'; +import { Button } from '../../components/component-library'; +import { Text } from '../../components/component-library/text/deprecated'; export default function DesktopPairingPage({ generateDesktopOtp, diff --git a/ui/pages/home/home.component.js b/ui/pages/home/home.component.js index 6bd76ea55..fff8e559c 100644 --- a/ui/pages/home/home.component.js +++ b/ui/pages/home/home.component.js @@ -42,12 +42,12 @@ import { ButtonIcon, ButtonIconSize, IconName, - Text, Box, ///: BEGIN:ONLY_INCLUDE_IN(build-main,build-mmi) ButtonLink, ///: END:ONLY_INCLUDE_IN } from '../../components/component-library'; +import { Text } from '../../components/component-library/text/deprecated'; import { ASSET_ROUTE, diff --git a/ui/pages/institutional/compliance-feature-page/compliance-feature-page.js b/ui/pages/institutional/compliance-feature-page/compliance-feature-page.js index 9820ff691..4ccba021a 100644 --- a/ui/pages/institutional/compliance-feature-page/compliance-feature-page.js +++ b/ui/pages/institutional/compliance-feature-page/compliance-feature-page.js @@ -17,8 +17,8 @@ import { ButtonIcon, ButtonIconSize, IconName, - Text, } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import Box from '../../../components/ui/box'; import ComplianceSettings from '../../../components/institutional/compliance-settings'; diff --git a/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.js b/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.js index 61a572f74..4f0257e77 100644 --- a/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.js +++ b/ui/pages/institutional/confirm-add-custodian-token/confirm-add-custodian-token.js @@ -19,13 +19,13 @@ import { setProviderType } from '../../../store/actions'; import { mmiActionsFactory } from '../../../store/institutional/institution-background'; import { Label, - Text, ButtonLink, Button, BUTTON_SIZES, BUTTON_VARIANT, Box, } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import { complianceActivated, getInstitutionalConnectRequests, diff --git a/ui/pages/institutional/confirm-add-institutional-feature/confirm-add-institutional-feature.js b/ui/pages/institutional/confirm-add-institutional-feature/confirm-add-institutional-feature.js index fa7f60b7c..627f7acb3 100644 --- a/ui/pages/institutional/confirm-add-institutional-feature/confirm-add-institutional-feature.js +++ b/ui/pages/institutional/confirm-add-institutional-feature/confirm-add-institutional-feature.js @@ -8,10 +8,10 @@ import { INSTITUTIONAL_FEATURES_DONE_ROUTE } from '../../../helpers/constants/ro import { MetaMetricsContext } from '../../../contexts/metametrics'; import { getMostRecentOverviewPage } from '../../../ducks/history/history'; import { - Text, BUTTON_SIZES, BUTTON_VARIANT, } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import { TextColor, TextVariant, diff --git a/ui/pages/institutional/connect-custody/account-list.js b/ui/pages/institutional/connect-custody/account-list.js index 0cf1a85fe..a4f868b18 100644 --- a/ui/pages/institutional/connect-custody/account-list.js +++ b/ui/pages/institutional/connect-custody/account-list.js @@ -18,7 +18,6 @@ import { useI18nContext } from '../../../hooks/useI18nContext'; import { Box, Button, - Text, Label, Icon, IconName, @@ -27,6 +26,7 @@ import { BUTTON_VARIANT, BUTTON_SIZES, } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard'; const getButtonLinkHref = (account) => { diff --git a/ui/pages/institutional/custody/custody.js b/ui/pages/institutional/custody/custody.js index 56eda94e7..0261eec90 100644 --- a/ui/pages/institutional/custody/custody.js +++ b/ui/pages/institutional/custody/custody.js @@ -14,7 +14,6 @@ import { MetaMetricsContext } from '../../../contexts/metametrics'; import { ButtonIcon, Button, - Text, Label, IconName, IconSize, @@ -22,6 +21,7 @@ import { BUTTON_VARIANT, Box, } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import { AlignItems, Display, diff --git a/ui/pages/institutional/institutional-entity-done-page/institutional-entity-done-page.js b/ui/pages/institutional/institutional-entity-done-page/institutional-entity-done-page.js index 495b15d88..48b8f0145 100644 --- a/ui/pages/institutional/institutional-entity-done-page/institutional-entity-done-page.js +++ b/ui/pages/institutional/institutional-entity-done-page/institutional-entity-done-page.js @@ -4,11 +4,11 @@ import { useSelector } from 'react-redux'; import { getMostRecentOverviewPage } from '../../../ducks/history/history'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { - Text, Box, Button, BUTTON_VARIANT, } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import { TextColor, TypographyVariant, diff --git a/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.js b/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.js index f3d83e988..b39fc78eb 100644 --- a/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.js +++ b/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.js @@ -17,7 +17,6 @@ import { showInteractiveReplacementTokenBanner, } from '../../../store/institutional/institution-background'; import { - Text, Label, Icon, ButtonLink, @@ -28,6 +27,7 @@ import { BUTTON_VARIANT, BUTTON_SIZES, } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import { OverflowWrap, TextColor, diff --git a/ui/pages/keychains/reveal-seed.js b/ui/pages/keychains/reveal-seed.js index ac4db39ab..3b045a173 100644 --- a/ui/pages/keychains/reveal-seed.js +++ b/ui/pages/keychains/reveal-seed.js @@ -22,7 +22,6 @@ import { import Box from '../../components/ui/box'; import { - Text, Label, BannerAlert, Button, @@ -33,6 +32,7 @@ import { TEXT_FIELD_TYPES, BUTTON_SIZES, } from '../../components/component-library'; +import { Text } from '../../components/component-library/text/deprecated'; import { useI18nContext } from '../../hooks/useI18nContext'; import { MetaMetricsContext } from '../../contexts/metametrics'; import ZENDESK_URLS from '../../helpers/constants/zendesk-url'; diff --git a/ui/pages/keyring-snaps/add-snap-account-modal/add-snap-account-modal.tsx b/ui/pages/keyring-snaps/add-snap-account-modal/add-snap-account-modal.tsx index 374f17b46..37ea6e02d 100644 --- a/ui/pages/keyring-snaps/add-snap-account-modal/add-snap-account-modal.tsx +++ b/ui/pages/keyring-snaps/add-snap-account-modal/add-snap-account-modal.tsx @@ -7,8 +7,8 @@ import { ModalContent, ModalHeader, ModalOverlay, - Text, } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import { AlignItems, Display, diff --git a/ui/pages/keyring-snaps/new-snap-account-page/new-snap-account-page.tsx b/ui/pages/keyring-snaps/new-snap-account-page/new-snap-account-page.tsx index 2ec9aea8c..5510fdf73 100644 --- a/ui/pages/keyring-snaps/new-snap-account-page/new-snap-account-page.tsx +++ b/ui/pages/keyring-snaps/new-snap-account-page/new-snap-account-page.tsx @@ -2,7 +2,8 @@ import { Snap } from '@metamask/snaps-utils'; import React, { useState, useEffect } from 'react'; import { shallowEqual, useSelector } from 'react-redux'; import { useHistory } from 'react-router-dom'; -import { Box, Text } from '../../../components/component-library'; +import { Box } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import { AlignItems, Display, diff --git a/ui/pages/keyring-snaps/snap-account-detail-page/detail.tsx b/ui/pages/keyring-snaps/snap-account-detail-page/detail.tsx index 7e47b59ad..32aa9db0f 100644 --- a/ui/pages/keyring-snaps/snap-account-detail-page/detail.tsx +++ b/ui/pages/keyring-snaps/snap-account-detail-page/detail.tsx @@ -1,5 +1,6 @@ import React from 'react'; -import { Box, Text } from '../../../components/component-library'; +import { Box } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import { FlexDirection, TextVariant, diff --git a/ui/pages/keyring-snaps/snap-account-detail-page/header.tsx b/ui/pages/keyring-snaps/snap-account-detail-page/header.tsx index ff44b01d4..e0aac1947 100644 --- a/ui/pages/keyring-snaps/snap-account-detail-page/header.tsx +++ b/ui/pages/keyring-snaps/snap-account-detail-page/header.tsx @@ -9,8 +9,8 @@ import { Icon, IconName, Tag, - Text, } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import { AlignItems, BackgroundColor, diff --git a/ui/pages/keyring-snaps/snap-account-detail-page/snap-account-detail-page.tsx b/ui/pages/keyring-snaps/snap-account-detail-page/snap-account-detail-page.tsx index 711446ef4..ae8cd738f 100644 --- a/ui/pages/keyring-snaps/snap-account-detail-page/snap-account-detail-page.tsx +++ b/ui/pages/keyring-snaps/snap-account-detail-page/snap-account-detail-page.tsx @@ -7,8 +7,8 @@ import { Box, Button, Tag, - Text, } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import { BlockSize, Display, diff --git a/ui/pages/keyring-snaps/snap-card/snap-card.tsx b/ui/pages/keyring-snaps/snap-card/snap-card.tsx index 30277e626..c44e068d4 100644 --- a/ui/pages/keyring-snaps/snap-card/snap-card.tsx +++ b/ui/pages/keyring-snaps/snap-card/snap-card.tsx @@ -9,14 +9,14 @@ import { Button, Icon, IconName, - Text, } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import { AlignItems, BackgroundColor, BorderColor, BorderRadius, - Color, + TextColor, Display, FlexDirection, IconColor, @@ -110,7 +110,7 @@ export default function SnapCard({
{snapTitle} diff --git a/ui/pages/onboarding-flow/pin-extension/pin-extension.js b/ui/pages/onboarding-flow/pin-extension/pin-extension.js index 0c14d704e..75b6e3e6c 100644 --- a/ui/pages/onboarding-flow/pin-extension/pin-extension.js +++ b/ui/pages/onboarding-flow/pin-extension/pin-extension.js @@ -18,7 +18,7 @@ import { import { MetaMetricsContext } from '../../../contexts/metametrics'; import { FIRST_TIME_FLOW_TYPES } from '../../../helpers/constants/onboarding'; import { getFirstTimeFlowType } from '../../../selectors'; -import { Text } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import OnboardingPinBillboard from './pin-billboard'; export default function OnboardingPinExtension() { diff --git a/ui/pages/onboarding-flow/secure-your-wallet/secure-your-wallet.js b/ui/pages/onboarding-flow/secure-your-wallet/secure-your-wallet.js index f2130d817..9775b7cbb 100644 --- a/ui/pages/onboarding-flow/secure-your-wallet/secure-your-wallet.js +++ b/ui/pages/onboarding-flow/secure-your-wallet/secure-your-wallet.js @@ -26,12 +26,12 @@ import { MetaMetricsEventName, } from '../../../../shared/constants/metametrics'; import { - Text, Box, Button, BUTTON_VARIANT, BUTTON_SIZES, } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import SkipSRPBackup from './skip-srp-backup-popover'; export default function SecureYourWallet() { diff --git a/ui/pages/onboarding-flow/welcome/welcome.js b/ui/pages/onboarding-flow/welcome/welcome.js index 00f83d79a..83b12dbbf 100644 --- a/ui/pages/onboarding-flow/welcome/welcome.js +++ b/ui/pages/onboarding-flow/welcome/welcome.js @@ -5,7 +5,7 @@ import { useHistory } from 'react-router-dom'; import { Carousel } from 'react-responsive-carousel'; import Mascot from '../../../components/ui/mascot'; import Button from '../../../components/ui/button'; -import { Text } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import CheckBox from '../../../components/ui/check-box'; import Box from '../../../components/ui/box'; import { diff --git a/ui/pages/permissions-connect/snaps/snap-install/snap-install.js b/ui/pages/permissions-connect/snaps/snap-install/snap-install.js index 52eec92ef..a69046846 100644 --- a/ui/pages/permissions-connect/snaps/snap-install/snap-install.js +++ b/ui/pages/permissions-connect/snaps/snap-install/snap-install.js @@ -22,9 +22,9 @@ import SnapAuthorshipHeader from '../../../../components/app/snaps/snap-authorsh import { AvatarIcon, IconName, - Text, ValidTag, } from '../../../../components/component-library'; +import { Text } from '../../../../components/component-library/text/deprecated'; import { getSnapName } from '../../../../helpers/utils/util'; import SnapPermissionsList from '../../../../components/app/snaps/snap-permissions-list'; import { useScrollRequired } from '../../../../hooks/useScrollRequired'; diff --git a/ui/pages/permissions-connect/snaps/snap-result/snap-result.js b/ui/pages/permissions-connect/snaps/snap-result/snap-result.js index 9deefe180..086f9f67d 100644 --- a/ui/pages/permissions-connect/snaps/snap-result/snap-result.js +++ b/ui/pages/permissions-connect/snaps/snap-result/snap-result.js @@ -21,9 +21,9 @@ import { AvatarIcon, IconName, IconSize, - Text, ValidTag, } from '../../../../components/component-library'; +import { Text } from '../../../../components/component-library/text/deprecated'; import PulseLoader from '../../../../components/ui/pulse-loader/pulse-loader'; import InstallError from '../../../../components/app/snaps/install-error/install-error'; import SnapAuthorshipHeader from '../../../../components/app/snaps/snap-authorship-header'; diff --git a/ui/pages/permissions-connect/snaps/snap-update/snap-update.js b/ui/pages/permissions-connect/snaps/snap-update/snap-update.js index c3b6fdef3..152d2a606 100644 --- a/ui/pages/permissions-connect/snaps/snap-update/snap-update.js +++ b/ui/pages/permissions-connect/snaps/snap-update/snap-update.js @@ -25,9 +25,9 @@ import SnapAuthorshipHeader from '../../../../components/app/snaps/snap-authorsh import { AvatarIcon, IconName, - Text, ValidTag, } from '../../../../components/component-library'; +import { Text } from '../../../../components/component-library/text/deprecated'; import { useOriginMetadata } from '../../../../hooks/useOriginMetadata'; import { getSnapName } from '../../../../helpers/utils/util'; import { useScrollRequired } from '../../../../hooks/useScrollRequired'; diff --git a/ui/pages/permissions-connect/snaps/snaps-connect/snaps-connect.js b/ui/pages/permissions-connect/snaps/snaps-connect/snaps-connect.js index ca3161185..caa8862e6 100644 --- a/ui/pages/permissions-connect/snaps/snaps-connect/snaps-connect.js +++ b/ui/pages/permissions-connect/snaps/snaps-connect/snaps-connect.js @@ -4,11 +4,8 @@ import PropTypes from 'prop-types'; import { useI18nContext } from '../../../../hooks/useI18nContext'; import Box from '../../../../components/ui/box'; import SiteOrigin from '../../../../components/ui/site-origin'; -import { - IconSize, - Text, - ValidTag, -} from '../../../../components/component-library'; +import { IconSize, ValidTag } from '../../../../components/component-library'; +import { Text } from '../../../../components/component-library/text/deprecated'; import { FlexDirection, TextVariant, diff --git a/ui/pages/send/send-content/add-recipient/add-recipient.component.js b/ui/pages/send/send-content/add-recipient/add-recipient.component.js index 67533a739..72f23f1ee 100644 --- a/ui/pages/send/send-content/add-recipient/add-recipient.component.js +++ b/ui/pages/send/send-content/add-recipient/add-recipient.component.js @@ -7,7 +7,7 @@ import ContactList from '../../../../components/app/contact-list'; import RecipientGroup from '../../../../components/app/contact-list/recipient-group/recipient-group.component'; import { ellipsify } from '../../send.utils'; import Confusable from '../../../../components/ui/confusable'; -import { Text } from '../../../../components/component-library'; +import { Text } from '../../../../components/component-library/text/deprecated'; import Box from '../../../../components/ui/box'; import { TextColor, diff --git a/ui/pages/send/send-content/send-asset-row/send-asset-row.component.js b/ui/pages/send/send-content/send-asset-row/send-asset-row.component.js index 8b8b6d165..b9b5f4c3b 100644 --- a/ui/pages/send/send-content/send-asset-row/send-asset-row.component.js +++ b/ui/pages/send/send-content/send-asset-row/send-asset-row.component.js @@ -12,7 +12,7 @@ import { AssetType, TokenStandard, } from '../../../../../shared/constants/transaction'; -import { Text } from '../../../../components/component-library'; +import { Text } from '../../../../components/component-library/text/deprecated'; import { TextVariant } from '../../../../helpers/constants/design-system'; export default class SendAssetRow extends Component { diff --git a/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js b/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js index 6f0a10fc2..8ff1a3b56 100644 --- a/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js +++ b/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js @@ -12,8 +12,8 @@ import { AvatarAccount, AvatarAccountSize, Box, - Text, } from '../../../../components/component-library'; +import { Text } from '../../../../components/component-library/text/deprecated'; import { AlignItems, Display, diff --git a/ui/pages/settings/contact-list-tab/view-contact/view-contact.component.js b/ui/pages/settings/contact-list-tab/view-contact/view-contact.component.js index 40c3e410f..21c80d990 100644 --- a/ui/pages/settings/contact-list-tab/view-contact/view-contact.component.js +++ b/ui/pages/settings/contact-list-tab/view-contact/view-contact.component.js @@ -11,8 +11,8 @@ import { ButtonIcon, ButtonIconSize, IconName, - Text, } from '../../../../components/component-library'; +import { Text } from '../../../../components/component-library/text/deprecated'; import Tooltip from '../../../../components/ui/tooltip'; import { useI18nContext } from '../../../../hooks/useI18nContext'; diff --git a/ui/pages/settings/experimental-tab/experimental-tab.component.js b/ui/pages/settings/experimental-tab/experimental-tab.component.js index ad4d0e627..0d6109899 100644 --- a/ui/pages/settings/experimental-tab/experimental-tab.component.js +++ b/ui/pages/settings/experimental-tab/experimental-tab.component.js @@ -7,7 +7,7 @@ import { } from '../../../helpers/utils/settings-search'; import { MetaMetricsEventCategory } from '../../../../shared/constants/metametrics'; import Typography from '../../../components/ui/typography/typography'; -import { Text } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import { FONT_WEIGHT, TextColor, diff --git a/ui/pages/settings/networks-tab/networks-list/networks-list.js b/ui/pages/settings/networks-tab/networks-list/networks-list.js index 7cb42959a..9fa629cd0 100644 --- a/ui/pages/settings/networks-tab/networks-list/networks-list.js +++ b/ui/pages/settings/networks-tab/networks-list/networks-list.js @@ -8,7 +8,7 @@ import { TextVariant, } from '../../../../helpers/constants/design-system'; import NetworksListItem from '../networks-list-item'; -import { Text } from '../../../../components/component-library'; +import { Text } from '../../../../components/component-library/text/deprecated'; const NetworksList = ({ networkIsSelected, diff --git a/ui/pages/settings/settings-tab/settings-tab.component.js b/ui/pages/settings/settings-tab/settings-tab.component.js index a823478c2..1f3e5770a 100644 --- a/ui/pages/settings/settings-tab/settings-tab.component.js +++ b/ui/pages/settings/settings-tab/settings-tab.component.js @@ -18,7 +18,7 @@ import { handleSettingsRefs, } from '../../../helpers/utils/settings-search'; import { ThemeType } from '../../../../shared/constants/preferences'; -import { Text } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; const sortedCurrencies = availableCurrencies.sort((a, b) => { return a.name.toLocaleLowerCase().localeCompare(b.name.toLocaleLowerCase()); diff --git a/ui/pages/settings/settings.component.js b/ui/pages/settings/settings.component.js index 583c1f156..337c17952 100644 --- a/ui/pages/settings/settings.component.js +++ b/ui/pages/settings/settings.component.js @@ -33,9 +33,9 @@ import { ButtonIconSize, Icon, IconName, - Text, Box, } from '../../components/component-library'; +import { Text } from '../../components/component-library/text/deprecated'; import { AlignItems, Color, diff --git a/ui/pages/settings/snaps/snaps-list-tab/snap-list-tab.js b/ui/pages/settings/snaps/snaps-list-tab/snap-list-tab.js index 86c722425..422552a5a 100644 --- a/ui/pages/settings/snaps/snaps-list-tab/snap-list-tab.js +++ b/ui/pages/settings/snaps/snaps-list-tab/snap-list-tab.js @@ -23,8 +23,8 @@ import { Icon, IconName, IconSize, - Text, } from '../../../../components/component-library'; +import { Text } from '../../../../components/component-library/text/deprecated'; const SnapListTab = () => { const t = useI18nContext(); diff --git a/ui/pages/settings/snaps/view-snap/view-snap.js b/ui/pages/settings/snaps/view-snap/view-snap.js index 5761fdea3..79d8ccb7e 100644 --- a/ui/pages/settings/snaps/view-snap/view-snap.js +++ b/ui/pages/settings/snaps/view-snap/view-snap.js @@ -33,7 +33,8 @@ import { getTargetSubjectMetadata, } from '../../../../selectors'; import { getSnapName } from '../../../../helpers/utils/util'; -import { Text, BUTTON_VARIANT } from '../../../../components/component-library'; +import { BUTTON_VARIANT } from '../../../../components/component-library'; +import { Text } from '../../../../components/component-library/text/deprecated'; import SnapPermissionsList from '../../../../components/app/snaps/snap-permissions-list'; import { SnapDelineator } from '../../../../components/app/snaps/snap-delineator'; import { DelineatorType } from '../../../../helpers/constants/snaps'; diff --git a/ui/pages/swaps/awaiting-signatures/awaiting-signatures.js b/ui/pages/swaps/awaiting-signatures/awaiting-signatures.js index dacb93729..da6b202d8 100644 --- a/ui/pages/swaps/awaiting-signatures/awaiting-signatures.js +++ b/ui/pages/swaps/awaiting-signatures/awaiting-signatures.js @@ -32,7 +32,7 @@ import { import SwapsFooter from '../swaps-footer'; import { MetaMetricsContext } from '../../../contexts/metametrics'; import { MetaMetricsEventCategory } from '../../../../shared/constants/metametrics'; -import { Text } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import SwapStepIcon from './swap-step-icon'; export default function AwaitingSignatures() { diff --git a/ui/pages/swaps/fee-card/fee-card.js b/ui/pages/swaps/fee-card/fee-card.js index c9856fcb3..8d02a2ee1 100644 --- a/ui/pages/swaps/fee-card/fee-card.js +++ b/ui/pages/swaps/fee-card/fee-card.js @@ -14,7 +14,7 @@ import { import { MetaMetricsContext } from '../../../contexts/metametrics'; import { MetaMetricsEventCategory } from '../../../../shared/constants/metametrics'; import { getUseCurrencyRateCheck } from '../../../selectors'; -import { Text } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; const GAS_FEES_LEARN_MORE_URL = 'https://community.metamask.io/t/what-is-gas-why-do-transactions-take-so-long/3172'; diff --git a/ui/pages/swaps/import-token/import-token.js b/ui/pages/swaps/import-token/import-token.js index eb8983262..373da1028 100644 --- a/ui/pages/swaps/import-token/import-token.js +++ b/ui/pages/swaps/import-token/import-token.js @@ -5,7 +5,7 @@ import UrlIcon from '../../../components/ui/url-icon'; import Popover from '../../../components/ui/popover'; import Button from '../../../components/ui/button'; import Box from '../../../components/ui/box'; -import { Text } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import ActionableMessage from '../../../components/ui/actionable-message/actionable-message'; import { TextVariant, diff --git a/ui/pages/swaps/list-with-search/list-with-search.js b/ui/pages/swaps/list-with-search/list-with-search.js index aeddbacb1..86a8897e2 100644 --- a/ui/pages/swaps/list-with-search/list-with-search.js +++ b/ui/pages/swaps/list-with-search/list-with-search.js @@ -13,7 +13,8 @@ import { TextVariant, BlockSize, } from '../../../helpers/constants/design-system'; -import { TextFieldSearch, Text } from '../../../components/component-library'; +import { TextFieldSearch } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import ItemList from '../searchable-item-list/item-list'; import { isValidHexAddress } from '../../../../shared/modules/hexstring-utils'; import { I18nContext } from '../../../contexts/i18n'; diff --git a/ui/pages/swaps/notification-page/notification-page.js b/ui/pages/swaps/notification-page/notification-page.js index a9835d4b1..67fb6e263 100644 --- a/ui/pages/swaps/notification-page/notification-page.js +++ b/ui/pages/swaps/notification-page/notification-page.js @@ -14,7 +14,8 @@ import { TEXT_ALIGN, IconColor, } from '../../../helpers/constants/design-system'; -import { Text, Icon, IconName } from '../../../components/component-library'; +import { Icon, IconName } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import { PREPARE_SWAP_ROUTE } from '../../../helpers/constants/routes'; import SwapsFooter from '../swaps-footer'; import { QUOTES_EXPIRED_ERROR } from '../../../../shared/constants/swaps'; diff --git a/ui/pages/swaps/prepare-swap-page/prepare-swap-page.js b/ui/pages/swaps/prepare-swap-page/prepare-swap-page.js index e1f0c5f0e..f83ad4800 100644 --- a/ui/pages/swaps/prepare-swap-page/prepare-swap-page.js +++ b/ui/pages/swaps/prepare-swap-page/prepare-swap-page.js @@ -115,12 +115,12 @@ import { IconSize, TextField, ButtonLink, - Text, Modal, ModalOverlay, ModalContent, ModalHeader, } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import { BannerAlert } from '../../../components/component-library/banner-alert'; import { SWAPS_NOTIFICATION_ROUTE } from '../../../helpers/constants/routes'; import ImportToken from '../import-token'; diff --git a/ui/pages/swaps/prepare-swap-page/quotes-loading-animation.js b/ui/pages/swaps/prepare-swap-page/quotes-loading-animation.js index 771e21639..f013dfe83 100644 --- a/ui/pages/swaps/prepare-swap-page/quotes-loading-animation.js +++ b/ui/pages/swaps/prepare-swap-page/quotes-loading-animation.js @@ -11,7 +11,7 @@ import { AlignItems, TextVariant, } from '../../../helpers/constants/design-system'; -import { Text } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import MascotBackgroundAnimation from '../mascot-background-animation/mascot-background-animation'; export default function QuotesLoadingAnimation(props) { diff --git a/ui/pages/swaps/prepare-swap-page/review-quote.js b/ui/pages/swaps/prepare-swap-page/review-quote.js index 13b9e9f57..a363747b9 100644 --- a/ui/pages/swaps/prepare-swap-page/review-quote.js +++ b/ui/pages/swaps/prepare-swap-page/review-quote.js @@ -115,11 +115,8 @@ import { TEXT_ALIGN, Size, } from '../../../helpers/constants/design-system'; -import { - BannerAlert, - Text, - ButtonLink, -} from '../../../components/component-library'; +import { BannerAlert, ButtonLink } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import { MetaMetricsEventCategory } from '../../../../shared/constants/metametrics'; import { isEqualCaseInsensitive } from '../../../../shared/modules/string-utils'; import { parseStandardTokenTransactionData } from '../../../../shared/modules/transaction.utils'; diff --git a/ui/pages/swaps/prepare-swap-page/smart-transactions-popover.js b/ui/pages/swaps/prepare-swap-page/smart-transactions-popover.js index 75c4056ac..839e11ece 100644 --- a/ui/pages/swaps/prepare-swap-page/smart-transactions-popover.js +++ b/ui/pages/swaps/prepare-swap-page/smart-transactions-popover.js @@ -14,7 +14,7 @@ import { FONT_WEIGHT, TextColor, } from '../../../helpers/constants/design-system'; -import { Text } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import PopoverCustomBackground from '../popover-custom-background/popover-custom-background'; export default function SmartTransactionsPopover({ diff --git a/ui/pages/swaps/prepare-swap-page/view-quote-price-difference.js b/ui/pages/swaps/prepare-swap-page/view-quote-price-difference.js index 1219fbd73..9db5fd2e9 100644 --- a/ui/pages/swaps/prepare-swap-page/view-quote-price-difference.js +++ b/ui/pages/swaps/prepare-swap-page/view-quote-price-difference.js @@ -12,11 +12,8 @@ import { BLOCK_SIZES, } from '../../../helpers/constants/design-system'; import { GasRecommendations } from '../../../../shared/constants/gas'; -import { - BannerAlert, - Text, - ButtonLink, -} from '../../../components/component-library'; +import { BannerAlert, ButtonLink } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; export default function ViewQuotePriceDifference(props) { const { diff --git a/ui/pages/swaps/slippage-buttons/slippage-buttons.js b/ui/pages/swaps/slippage-buttons/slippage-buttons.js index 64f81d7f9..b649e2442 100644 --- a/ui/pages/swaps/slippage-buttons/slippage-buttons.js +++ b/ui/pages/swaps/slippage-buttons/slippage-buttons.js @@ -15,7 +15,7 @@ import { } from '../../../helpers/constants/design-system'; import { getTranslatedStxErrorMessage } from '../swaps.util'; import { Slippage } from '../../../../shared/constants/swaps'; -import { Text } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; export default function SlippageButtons({ onSelect, diff --git a/ui/pages/swaps/smart-transaction-status/smart-transaction-status.js b/ui/pages/swaps/smart-transaction-status/smart-transaction-status.js index 9285fcb5e..7abba8697 100644 --- a/ui/pages/swaps/smart-transaction-status/smart-transaction-status.js +++ b/ui/pages/swaps/smart-transaction-status/smart-transaction-status.js @@ -31,7 +31,7 @@ import { DEFAULT_ROUTE, BUILD_QUOTE_ROUTE, } from '../../../helpers/constants/routes'; -import { Text } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import Box from '../../../components/ui/box'; import UrlIcon from '../../../components/ui/url-icon'; import { diff --git a/ui/pages/swaps/swaps-banner-alert/swaps-banner-alert.js b/ui/pages/swaps/swaps-banner-alert/swaps-banner-alert.js index 87a4e3ee2..ef9bc0063 100644 --- a/ui/pages/swaps/swaps-banner-alert/swaps-banner-alert.js +++ b/ui/pages/swaps/swaps-banner-alert/swaps-banner-alert.js @@ -11,7 +11,8 @@ import { Size, TextVariant, } from '../../../helpers/constants/design-system'; -import { ButtonLink, Text } from '../../../components/component-library'; +import { ButtonLink } from '../../../components/component-library'; +import { Text } from '../../../components/component-library/text/deprecated'; import { QUOTES_EXPIRED_ERROR, SWAP_FAILED_ERROR, diff --git a/ui/pages/token-allowance/token-allowance.js b/ui/pages/token-allowance/token-allowance.js index 5ab20f615..aeae9d5c5 100644 --- a/ui/pages/token-allowance/token-allowance.js +++ b/ui/pages/token-allowance/token-allowance.js @@ -65,7 +65,8 @@ import { useSimulationFailureWarning } from '../../hooks/useSimulationFailureWar import SimulationErrorMessage from '../../components/ui/simulation-error-message'; import LedgerInstructionField from '../../components/app/ledger-instruction-field/ledger-instruction-field'; import SecurityProviderBannerMessage from '../../components/app/security-provider-banner-message/security-provider-banner-message'; -import { Text, Icon, IconName } from '../../components/component-library'; +import { Icon, IconName } from '../../components/component-library'; +import { Text } from '../../components/component-library/text/deprecated'; import { ConfirmPageContainerWarning } from '../../components/app/confirm-page-container/confirm-page-container-content'; import CustomNonce from '../../components/app/custom-nonce'; diff --git a/ui/pages/token-details/token-details-page.js b/ui/pages/token-details/token-details-page.js index 17f058187..9b9d515ef 100644 --- a/ui/pages/token-details/token-details-page.js +++ b/ui/pages/token-details/token-details-page.js @@ -28,8 +28,8 @@ import { ButtonIcon, ButtonIconSize, IconName, - Text, } from '../../components/component-library'; +import { Text } from '../../components/component-library/text/deprecated'; export default function TokenDetailsPage() { const dispatch = useDispatch(); From 1295474dc3101d9c98f0d59f8e131536b639316f Mon Sep 17 00:00:00 2001 From: Daniel <80175477+dan437@users.noreply.github.com> Date: Fri, 14 Jul 2023 20:48:46 +0200 Subject: [PATCH 052/172] Show a balance for the Token To, update position of the MM fee, removes a link (#20030) --- app/_locales/en/messages.json | 10 +++- test/e2e/swaps/shared.js | 4 +- .../exchange-rate-display.test.js.snap | 2 +- .../exchange-rate-display.js | 11 +++- .../swaps/exchange-rate-display/index.scss | 4 ++ ...swaps-quotes-stories-metadata.test.js.snap | 2 +- .../main-quote-summary.test.js.snap | 2 +- .../prepare-swap-page/prepare-swap-page.js | 16 +++++- .../swaps/prepare-swap-page/review-quote.js | 55 +++++++++---------- .../prepare-swap-page/review-quote.test.js | 9 ++- .../__snapshots__/view-quote.test.js.snap | 4 +- 11 files changed, 72 insertions(+), 47 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index d801f3383..862ca35ce 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -3086,9 +3086,6 @@ "message": "You have (1) pending transaction.", "description": "$1 is count of pending transactions" }, - "percentage": { - "message": "$1%" - }, "permissionRequest": { "message": "Permission request" }, @@ -4469,6 +4466,10 @@ "message": "Includes a $1% MetaMask fee.", "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." }, + "swapIncludesMetaMaskFeeViewAllQuotes": { + "message": "Includes a $1% MetaMask fee – $2", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number and $2 is a link to view all quotes." + }, "swapLearnMore": { "message": "Learn more about Swaps" }, @@ -5233,6 +5234,9 @@ "viewAllDetails": { "message": "View all details" }, + "viewAllQuotes": { + "message": "view all quotes" + }, "viewContact": { "message": "View contact" }, diff --git a/test/e2e/swaps/shared.js b/test/e2e/swaps/shared.js index 12fbe4ccb..efef3b4b0 100644 --- a/test/e2e/swaps/shared.js +++ b/test/e2e/swaps/shared.js @@ -173,9 +173,7 @@ const checkNotification = async (driver, options) => { }; const changeExchangeRate = async (driver) => { - await driver.clickElement( - '[data-testid="exchange-rate-display-base-symbol"]', - ); + await driver.clickElement('[data-testid="review-quote-view-all-quotes"]'); await driver.waitForSelector({ text: 'Quote details', tag: 'h2' }); const networkFees = await driver.findElements( diff --git a/ui/pages/swaps/exchange-rate-display/__snapshots__/exchange-rate-display.test.js.snap b/ui/pages/swaps/exchange-rate-display/__snapshots__/exchange-rate-display.test.js.snap index 7dc3b1256..bdd3b3dfa 100644 --- a/ui/pages/swaps/exchange-rate-display/__snapshots__/exchange-rate-display.test.js.snap +++ b/ui/pages/swaps/exchange-rate-display/__snapshots__/exchange-rate-display.test.js.snap @@ -6,7 +6,7 @@ exports[`ExchangeRateDisplay renders the component with initial props 1`] = ` class="exchange-rate-display" >
diff --git a/ui/pages/swaps/exchange-rate-display/exchange-rate-display.js b/ui/pages/swaps/exchange-rate-display/exchange-rate-display.js index 413730c28..12a38e12c 100644 --- a/ui/pages/swaps/exchange-rate-display/exchange-rate-display.js +++ b/ui/pages/swaps/exchange-rate-display/exchange-rate-display.js @@ -72,6 +72,13 @@ export default function ExchangeRateDisplay({ rateToDisplay = formatSwapsValueForDisplay(rate); } + const quoteRateClassName = onQuotesClick + ? 'exchange-rate-display__quote-rate' + : 'exchange-rate-display__quote-rate--no-link'; + const quoteRateColor = onQuotesClick + ? TextColor.primaryDefault + : TextColor.textDefault; + return (
1 diff --git a/ui/pages/swaps/exchange-rate-display/index.scss b/ui/pages/swaps/exchange-rate-display/index.scss index 9a397f982..f59713639 100644 --- a/ui/pages/swaps/exchange-rate-display/index.scss +++ b/ui/pages/swaps/exchange-rate-display/index.scss @@ -19,4 +19,8 @@ &__quote-rate { cursor: pointer; } + + &__quote-rate--no-link { + cursor: text; + } } diff --git a/ui/pages/swaps/loading-swaps-quotes/__snapshots__/loading-swaps-quotes-stories-metadata.test.js.snap b/ui/pages/swaps/loading-swaps-quotes/__snapshots__/loading-swaps-quotes-stories-metadata.test.js.snap index 6581c8123..66be56d52 100644 --- a/ui/pages/swaps/loading-swaps-quotes/__snapshots__/loading-swaps-quotes-stories-metadata.test.js.snap +++ b/ui/pages/swaps/loading-swaps-quotes/__snapshots__/loading-swaps-quotes-stories-metadata.test.js.snap @@ -27,4 +27,4 @@ exports[`storiesMetadata matches expected values for storiesMetadata 1`] = ` "icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASkAAAB5CAYAAABlYNfBAAAACXBIWXMAACxLAAAsSwGlPZapAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAlASURBVHgB7d3/eeO2GcDx1336f3UThNcF4g3KLNA4HaDnywC5Xgeo6Q5Q+zpAz+kCd+0AJyUDxNcFTsoCsbtA3gIVFL0CIRGgKMm2vp/nwWPxF0hT4isABCERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADhCJ4LeVLVyf05d+sylZy7dufSjS7OTk5OPgrXcufN/KpfO16zyfqhzmLGvEjOX7mWA9zgcVx3SwrXL916AvtwHa+TShUtT3cwvfxUCGSLuvJy4dLPh/H2Qgfhg4NIXOrw7l9659EJ6CMfVmPx+5vOCrYSgc6dlpi79SbBC50FquuG8+Qt2JAPQ3QUp65NLdY/jIkh1+LUgi/vwXLk/qWDz/6J/+Ov56p+9uCqXrtz2n7li/GvBoppzJvNzs8m5S9eyG/eyfM9KjGT1/V147tIH979duvf5UoB98gEq8c35dt03p5t/qumqzFvBohT1zpyXqUvnLr3U1ZLqIFU+bZekfInlXHoIefkq/9ma99jnnVVypiSFQei8/UmjC6rO3LZOfIiPuuoXLszn0Tn5h1kWX7RbV/mGDFKJfKtEsPo55zNCkMLWwgcwDlBVwfYXmnYqRypcmC+jC/PULIvbjhrZ0q6ClMnflwyvo+PuLAUSpLA194EZRx+8unD7qaaN5UiFC9qe108dy3+QLe06SIV9xMfdWZoiSOX5lSApfMBqM+vGNYhOJFO4CCoz61vzutbCgPcU6LK/Um1m/zNezaXvzPTpIzlX/rj/aqZ9H8RasDWC1Hrn0XTpHZsL83oi7TuDF3KcavPaX9g3iXXemNf+Yv9SHoe4c+fngq0RpNazF8bElaJmkilRiroMvYgnZp4vIQzSD+gR8QHnGzP9MT6vbtr/ic9Vr86S+2SOe2ZmE6QGQJBKCNULG0BupMxKKcpUE22Vz+d/NA3ooap3Ksv/2c94s251l/5tpkePqHo8EwyKIJV2Fk1/J5lSpSjz+n3HfuK8LnTeH8unRrag897yi7wO0V/LFzVeRfM2ndebaNs/CoC56C7NtHDbqdn2tmP5uCOvM13Vq4+VtrtSNLJn2n4M5kPG+mOz/k99q8e6h7t7sjzmW7OfHzKOi7t7HShJpdlq2EwyabsUlXqkY+XOlWzgqom+5DUxsy56Xqg2GPqn9xvZI10+7V8tZslq1Te5maze+fP/95k8fPY9ZTSDARCk0mwg+I/ks21RPhikLkT7wR1lBJ3X0XEV3RVMBM5G9s9X1+LG75wqtA/S9yaPB1vlC4H4PJr9vQBDS1SNcp/DOo+2e5G5XpWRd9ybuZYM4X+Zmu0O8uygtqt67wq2exdVh4pLkrq/zpzTaB+nGcdFda8DJam2KprOLbLnlKJy9pfSRMeRW5pqZH0j/l5oe8QDP+N97uYu/T2ady4PTPgf/XtSmdkTBj4cBkGq26xrhVCyqcyspiC/30iH0MfKVvtq7RhoLXyL23UuS/p6DSiupt0XBHDPX+i2yvd7eSBCSciPyOpLqPaLw0etrwXYBW2PXFBnbDM2608L8z+X/GOz+7nbVPWJqh5FdyiHohtGPCjII354t7hKpLsbquVa04MgNgV5Ud3rwKB3bVXJytp+xq+R3bk0+1o0or9OHJPvj1SZWYccbK82r+M7djn8Nv+SZR8rX5o6l+3Os8/DjxHW59GkdYPeLVzu++4pjoy2+ybVHeuPS0osukVJKmwfN6KfRssfRGN5OJaNIx4U5nPXNx9l+OBHjTaptrihfG2bUfhA1WZWI+XuCtdvZPUYrxLLq/B6JgdoLPc0PeLBRPqz7ViVPozHZBbPGH7lSk+/LRklA/mo7nV7tmFZY17n3tGLqwr/lQK+Ed1doD7wLILTohHd9zuqZLWx/M2BGssXbOdLH7W+36KkYPurLUZGmEh/76WsD9zCLPz9yN07HIRm9pNKrJf1pL62+0nV0oO2B+SLHaSx3Bxf16/BbOungmPZeT+pPpTqXhaqe21xda9as15jXs8k/yHkKpru+23cVY17KQeiyxEPKtmdxzQyArZAkIqEPkk2ULXapMK3nS05fVtQrfo8sb8+ftex/JUcTmrEg13s4xvBk0ebVNpMlg+K1onlTbTujeSrzOtepagQJBtZPQaf7BhV/i5lfcDGXBtE/WgQf5Dt+cDk+1nVYdq3x434WXIcHW3f5h+ZZXFb1FVBvqNo217dA7TdqbMy+dtb9VPd8+ifa9p/sp5/zMz7dWnetEk9blT30uISji0VNNGydaNLptTR9EQKhYurNrN+edwllChsW1Ul6V9d3qXUiAe5z+rluIn29WAekwH2Zl2JJ1GKKioJaftHJKvC7eOOmtM1642j/ZzKnmi74+Ugv0Ic5T+OSh+jjm0oSeHp0cRzctsEGW0HuLEUyt2/zn/mXXcVKDYcn0/xD39mdc0o3EdRlY8ghSdJ24+vvI2nC/O7iLYvuni13b+q6Vj/uuRCHoKmx3+qZEDhwn4WnYsPGdsQpPD06ObOiFVBPnEpqnTc9FF0LP71KGMbW+3qPUZ45jGmRjzYSQlOC38tmCD1uNFwvtm6DpE3uf2iQmCIq3aNlIlHNWgybrv75X820/7xnr/JbtXmdc445n3Foynwa8E4XtpuB1ItG773Ntr2WgroFo31pSWObWiPBu0t9rWo8q2UFDvWpySFp0nn1aY40ExdeqHrG679NhfaHhDttvTC1XY1ryrYNlUF+6QDBw8dYHC7Hvv0QfEmusBrWX98BCk8XWsC1cJYzY9uhunUaI19AtRFlEfxnbLEheA1MiBN33H7UnZI02NEXWWuS5DC06Ttnui5/HalAcpX82ywu5UedFk1mu7qYtD2iAfZIxQMsN/OmwNKkHrUaDgv4Bqr/W3855LfIDxx6Qu/XY/ny3ypyW8zC+kr6cHt1//xA+t9bfL60aW/yAB0ObidmPx31WDe2r3Mf4B1FtK9rB95wZ5Ln0oHG9wVfxwzkxA5EfQSvrFrmT/Q618vRkvwAcA/VjPhwVcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwJH7H5NlZI/0GQ+cAAAAAElFTkSuQmCC", }, } -`; \ No newline at end of file +`; diff --git a/ui/pages/swaps/main-quote-summary/__snapshots__/main-quote-summary.test.js.snap b/ui/pages/swaps/main-quote-summary/__snapshots__/main-quote-summary.test.js.snap index 7b58f794f..b36e37007 100644 --- a/ui/pages/swaps/main-quote-summary/__snapshots__/main-quote-summary.test.js.snap +++ b/ui/pages/swaps/main-quote-summary/__snapshots__/main-quote-summary.test.js.snap @@ -81,7 +81,7 @@ exports[`MainQuoteSummary renders the component with initial props 4`] = ` class="exchange-rate-display main-quote-summary__exchange-rate-display" >
diff --git a/ui/pages/swaps/prepare-swap-page/prepare-swap-page.js b/ui/pages/swaps/prepare-swap-page/prepare-swap-page.js index f83ad4800..654d2b766 100644 --- a/ui/pages/swaps/prepare-swap-page/prepare-swap-page.js +++ b/ui/pages/swaps/prepare-swap-page/prepare-swap-page.js @@ -586,7 +586,10 @@ export default function PrepareSwapPage({ ); }; - const swapYourTokenBalance = `${t('balance')}: ${fromTokenString || '0'}`; + const yourTokenFromBalance = `${t('balance')}: ${fromTokenString || '0'}`; + const yourTokenToBalance = `${t('balance')}: ${ + selectedToToken?.string || '0' + }`; const isDirectWrappingEnabled = shouldEnableDirectWrapping( chainId, @@ -883,7 +886,7 @@ export default function PrepareSwapPage({ alignItems={AlignItems.stretch} >
- {fromTokenSymbol && swapYourTokenBalance} + {fromTokenSymbol && yourTokenFromBalance} {showMaxBalanceLink && (
+ +
+ {selectedToToken?.string && yourTokenToBalance} +
+
{!showReviewQuote && toTokenIsNotDefault && occurrences < 2 && ( diff --git a/ui/pages/swaps/prepare-swap-page/review-quote.js b/ui/pages/swaps/prepare-swap-page/review-quote.js index a363747b9..3e73d97ce 100644 --- a/ui/pages/swaps/prepare-swap-page/review-quote.js +++ b/ui/pages/swaps/prepare-swap-page/review-quote.js @@ -1047,7 +1047,6 @@ export default function ReviewQuote({ setReceiveToAmount }) { > @@ -1063,39 +1062,11 @@ export default function ReviewQuote({ setReceiveToAmount }) { secondaryTokenValue={destinationValue} secondaryTokenDecimals={destinationTokenDecimals} secondaryTokenSymbol={destinationTokenSymbol} - arrowColor="var(--color-primary-default)" boldSymbols={false} className="main-quote-summary__exchange-rate-display" - onQuotesClick={ - /* istanbul ignore next */ - () => { - trackAllAvailableQuotesOpened(); - setSelectQuotePopoverShown(true); - } - } showIconForSwappingTokens={false} /> - - - {t('swapMetaMaskFee')} - - - {t('percentage', [metaMaskFee])} - - )} + + + {t('swapIncludesMetaMaskFeeViewAllQuotes', [ + metaMaskFee, + { + trackAllAvailableQuotesOpened(); + setSelectQuotePopoverShown(true); + } + } + size={Size.inherit} + > + {t('viewAllQuotes')} + , + ])} + +
{ const { getByText } = renderWithProvider(, store); expect(getByText('New quotes in')).toBeInTheDocument(); expect(getByText('Quote rate')).toBeInTheDocument(); - expect(getByText('MetaMask fee')).toBeInTheDocument(); + expect(getByText('Includes a 1% MetaMask fee –')).toBeInTheDocument(); + expect(getByText('view all quotes')).toBeInTheDocument(); expect(getByText('Estimated gas fee')).toBeInTheDocument(); expect(getByText('0.00008 ETH')).toBeInTheDocument(); expect(getByText('Max fee:')).toBeInTheDocument(); @@ -71,7 +72,8 @@ describe('ReviewQuote', () => { const { getByText } = renderWithProvider(, store); expect(getByText('New quotes in')).toBeInTheDocument(); expect(getByText('Quote rate')).toBeInTheDocument(); - expect(getByText('MetaMask fee')).toBeInTheDocument(); + expect(getByText('Includes a 1% MetaMask fee –')).toBeInTheDocument(); + expect(getByText('view all quotes')).toBeInTheDocument(); expect(getByText('Estimated gas fee')).toBeInTheDocument(); expect(getByText('0.00008 ETH')).toBeInTheDocument(); expect(getByText('Max fee:')).toBeInTheDocument(); @@ -93,7 +95,8 @@ describe('ReviewQuote', () => { const { getByText } = renderWithProvider(, store); expect(getByText('New quotes in')).toBeInTheDocument(); expect(getByText('Quote rate')).toBeInTheDocument(); - expect(getByText('MetaMask fee')).toBeInTheDocument(); + expect(getByText('Includes a 1% MetaMask fee –')).toBeInTheDocument(); + expect(getByText('view all quotes')).toBeInTheDocument(); expect(getByText('Estimated gas fee')).toBeInTheDocument(); expect(getByText('0.00008 ETH')).toBeInTheDocument(); expect(getByText('Max fee:')).toBeInTheDocument(); diff --git a/ui/pages/swaps/view-quote/__snapshots__/view-quote.test.js.snap b/ui/pages/swaps/view-quote/__snapshots__/view-quote.test.js.snap index 9d8204c51..d9ed7df32 100644 --- a/ui/pages/swaps/view-quote/__snapshots__/view-quote.test.js.snap +++ b/ui/pages/swaps/view-quote/__snapshots__/view-quote.test.js.snap @@ -38,7 +38,7 @@ exports[`ViewQuote renders the component with EIP-1559 enabled 2`] = ` class="exchange-rate-display main-quote-summary__exchange-rate-display" >
@@ -110,7 +110,7 @@ exports[`ViewQuote renders the component with initial props 2`] = ` class="exchange-rate-display main-quote-summary__exchange-rate-display" >
From 775ca0dc313bc0590db3a497f9003848f09b2092 Mon Sep 17 00:00:00 2001 From: Garrett Bear Date: Fri, 14 Jul 2023 11:50:47 -0700 Subject: [PATCH 053/172] Feat/15438/create ds checkbox component (#19808) * add ds checkbox --------- Co-authored-by: Garrett Bear --------- Co-authored-by: georgewrmarshall --- app/images/icons/check-bold.svg | 1 + app/images/icons/minus-bold.svg | 1 + .../component-library/checkbox/README.mdx | 218 ++++++++++++++++++ .../__snapshots__/checkbox.test.tsx.snap | 18 ++ .../component-library/checkbox/checkbox.scss | 53 +++++ .../checkbox/checkbox.stories.tsx | 177 ++++++++++++++ .../checkbox/checkbox.test.tsx | 182 +++++++++++++++ .../component-library/checkbox/checkbox.tsx | 124 ++++++++++ .../checkbox/checkbox.types.ts | 74 ++++++ .../component-library/checkbox/index.ts | 2 + .../component-library-components.scss | 1 + .../component-library/icon/icon.types.ts | 2 + ui/components/component-library/index.js | 1 + 13 files changed, 854 insertions(+) create mode 100644 app/images/icons/check-bold.svg create mode 100644 app/images/icons/minus-bold.svg create mode 100644 ui/components/component-library/checkbox/README.mdx create mode 100644 ui/components/component-library/checkbox/__snapshots__/checkbox.test.tsx.snap create mode 100644 ui/components/component-library/checkbox/checkbox.scss create mode 100644 ui/components/component-library/checkbox/checkbox.stories.tsx create mode 100644 ui/components/component-library/checkbox/checkbox.test.tsx create mode 100644 ui/components/component-library/checkbox/checkbox.tsx create mode 100644 ui/components/component-library/checkbox/checkbox.types.ts create mode 100644 ui/components/component-library/checkbox/index.ts diff --git a/app/images/icons/check-bold.svg b/app/images/icons/check-bold.svg new file mode 100644 index 000000000..a011e3386 --- /dev/null +++ b/app/images/icons/check-bold.svg @@ -0,0 +1 @@ + diff --git a/app/images/icons/minus-bold.svg b/app/images/icons/minus-bold.svg new file mode 100644 index 000000000..16026831c --- /dev/null +++ b/app/images/icons/minus-bold.svg @@ -0,0 +1 @@ + diff --git a/ui/components/component-library/checkbox/README.mdx b/ui/components/component-library/checkbox/README.mdx new file mode 100644 index 000000000..dc2f04e8a --- /dev/null +++ b/ui/components/component-library/checkbox/README.mdx @@ -0,0 +1,218 @@ +import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; + +import { Checkbox } from './checkbox'; + +# Checkbox + +Checkbox is a graphical element that allows users to select one or more options from a set of choices. + + + + + +## Props + +The `Checkbox` accepts all props below as well as all [Box](/docs/components-componentlibrary-box--docs#props) component props + + + +### Label + +Use the `label` string prop to set the label of the `Checkbox` + + + + + +```jsx +import { Checkbox } from '../../component-library'; + +; +``` + +### IsChecked + +Use the `isChecked` boolean prop to set the checked state of the `Checkbox` + + + + + +```jsx +import { Checkbox } from '../../component-library'; + +; +``` + +### IsIndeterminate + +Use the `isIndeterminate` boolean prop to set the indeterminate state of the `Checkbox` + + + + + +```jsx +import React from 'react'; +import { Checkbox, Box } from '../../component-library'; + +const [checkedItems, setCheckedItems] = React.useState([false, true, false]); + +const allChecked = checkedItems.every(Boolean); +const isIndeterminate = checkedItems.some(Boolean) && !allChecked; + +const handleIndeterminateChange = () => { + if (allChecked || isIndeterminate) { + setCheckedItems([false, false, false]); + } else { + setCheckedItems([true, true, true]); + } +}; + +const handleCheckboxChange = (index, value) => { + const newCheckedItems = [...checkedItems]; + newCheckedItems[index] = value; + setCheckedItems(newCheckedItems); +}; + + + + handleCheckboxChange(0, e.target.checked)} + label="Checkbox 1" + /> + handleCheckboxChange(1, e.target.checked)} + label="Checkbox 2" + /> + handleCheckboxChange(2, e.target.checked)} + label="Checkbox 3" + /> + +``` + +### IsDisabled + +Use the `isDisabled` boolean prop to set the disabled state of the `Checkbox` + + + + + +```jsx +import { Checkbox } from '../../component-library'; + +; +``` + +### IsReadOnly + +Use the `isReadOnly` boolean prop to set the readOnly attribute of the `Checkbox` + + + + + +```jsx +import { Checkbox } from '../../component-library'; + +; +``` + +### OnChange + +Use the `onChange` function prop to set the onChange handler of the `Checkbox` + + + + + +```jsx +import React from 'react'; +import { Checkbox } from '../../component-library'; + +const [isChecked, setIsChecked] = React.useState(false); + + setIsChecked(!isChecked)} + isChecked={isChecked} + label="isReadOnly demo" +/>; +``` + +### IsRequired + +Use the `isRequired` boolean prop to set the required attribute of the `Checkbox` + + + + + +```jsx +import { Checkbox } from '../../component-library'; + +; +``` + +### Title + +Use the `title` string prop to set the title attribute of the `Checkbox` +The title attribute is used to provide additional context or information about the checkbox. It is primarily used for browser native tooltip functionality. + + + + + +```jsx +import { Checkbox } from '../../component-library'; + +; +``` + +### Name + +Use the `name` string prop to set the name attribute of the `Checkbox` +This is best used when working with a form and submitting the value of the `Checkbox` + + + + + +```jsx +import { Checkbox } from '../../component-library'; + +; +``` + +### InputProps + +Use the `inputProps` object prop to add additonal props or attributes to the hidden input element +If needing to pass a ref to the input element, use the `inputRef` prop + + + + + +```jsx +import { Checkbox } from '../../component-library'; + +; +``` diff --git a/ui/components/component-library/checkbox/__snapshots__/checkbox.test.tsx.snap b/ui/components/component-library/checkbox/__snapshots__/checkbox.test.tsx.snap new file mode 100644 index 000000000..5df6da8de --- /dev/null +++ b/ui/components/component-library/checkbox/__snapshots__/checkbox.test.tsx.snap @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Checkbox should render the Checkbox without crashing 1`] = ` +
+ +
+`; diff --git a/ui/components/component-library/checkbox/checkbox.scss b/ui/components/component-library/checkbox/checkbox.scss new file mode 100644 index 000000000..2fe95e07a --- /dev/null +++ b/ui/components/component-library/checkbox/checkbox.scss @@ -0,0 +1,53 @@ +.mm-checkbox { + cursor: pointer; + + &__input-wrapper { + position: relative; + } + + &__input { + -webkit-appearance: none; + appearance: none; + width: 20px; + height: 20px; + + &:hover:not(:disabled) { + background-color: var(--color-background-default-hover); + } + + &:focus { + border-color: var(--color-primary-default); + } + + &:disabled { + color: var(--color-icon-muted); + cursor: not-allowed; + } + } + + &__input--checked:hover:not(:disabled), + &__input--indeterminate:hover:not(:disabled) { + border-color: var(--color-primary-alternative); + background-color: var(--color-primary-alternative); + } + + &__input--checked#{&}__input--readonly, + &__input--checked#{&}__input--readonly:hover, + &__input--indeterminate#{&}__input--readonly, + &__input--indeterminate#{&}__input--readonly:hover { + border-color: var(--color-icon-alternative); + background-color: var(--color-icon-alternative); + cursor: not-allowed; + } + + &--disabled { + opacity: var(--opacity-disabled); + } + + &__icon { + position: absolute; + top: 0; + left: 0; + pointer-events: none; + } +} diff --git a/ui/components/component-library/checkbox/checkbox.stories.tsx b/ui/components/component-library/checkbox/checkbox.stories.tsx new file mode 100644 index 000000000..6ee20f4f2 --- /dev/null +++ b/ui/components/component-library/checkbox/checkbox.stories.tsx @@ -0,0 +1,177 @@ +import { StoryFn, Meta } from '@storybook/react'; +import { useArgs } from '@storybook/client-api'; +import React from 'react'; + +import { Box } from '..'; +import { + BorderColor, + Display, + FlexDirection, +} from '../../../helpers/constants/design-system'; +import README from './README.mdx'; + +import { Checkbox } from '.'; + +export default { + title: 'Components/ComponentLibrary/Checkbox', + component: Checkbox, + parameters: { + docs: { + page: README, + }, + }, + argTypes: { + label: { + control: 'text', + }, + name: { + control: 'text', + }, + id: { + control: 'text', + }, + }, +} as Meta; + +const Template: StoryFn = (args) => { + const [{ isChecked }, updateArgs] = useArgs(); + return ( + + updateArgs({ + isChecked: !isChecked, + }) + } + isChecked={isChecked} + /> + ); +}; + +export const DefaultStory = Template.bind({}); +DefaultStory.storyName = 'Default'; + +export const Label = Template.bind({}); +Label.args = { + label: 'Checkbox label', +}; + +export const Id = Template.bind({}); +Id.args = { + label: 'Id demo', + id: 'id-demo', +}; + +export const IsChecked = Template.bind({}); +IsChecked.args = { + isChecked: true, + label: 'isChecked demo', +}; + +export const IsIndeterminate = (args) => { + const [checkedItems, setCheckedItems] = React.useState([false, true, false]); + + const allChecked = checkedItems.every(Boolean); + const isIndeterminate = checkedItems.some(Boolean) && !allChecked; + + const handleIndeterminateChange = () => { + if (allChecked || isIndeterminate) { + setCheckedItems([false, false, false]); + } else { + setCheckedItems([true, true, true]); + } + }; + + const handleCheckboxChange = (index, value) => { + const newCheckedItems = [...checkedItems]; + newCheckedItems[index] = value; + setCheckedItems(newCheckedItems); + }; + + return ( +
+ + + handleCheckboxChange(0, e.target.checked)} + label="Checkbox 1" + /> + handleCheckboxChange(1, e.target.checked)} + label="Checkbox 2" + /> + handleCheckboxChange(2, e.target.checked)} + label="Checkbox 3" + /> + +
+ ); +}; + +IsIndeterminate.args = { + label: 'isIndeterminate demo', + isIndeterminate: true, +}; + +export const IsDisabled = Template.bind({}); + +IsDisabled.args = { + isDisabled: true, + label: 'isDisabled demo', +}; + +export const IsReadOnly = Template.bind({}); + +IsReadOnly.args = { + isReadOnly: true, + isChecked: true, + label: 'isReadOnly demo', +}; + +export const OnChange = Template.bind({}); +OnChange.args = { + label: 'onChange demo', +}; + +export const IsRequired = Template.bind({}); + +IsRequired.args = { + isRequired: true, + isChecked: true, + label: 'isRequired demo', +}; + +export const Title = Template.bind({}); + +Title.args = { + title: 'Apples', + label: 'Inspect to see title attribute', +}; + +export const Name = Template.bind({}); + +Name.args = { + name: 'pineapple', + label: 'Inspect to see name attribute', +}; + +export const InputProps = Template.bind({}); +InputProps.args = { + inputProps: { borderColor: BorderColor.errorDefault }, + label: 'inputProps demo', +}; diff --git a/ui/components/component-library/checkbox/checkbox.test.tsx b/ui/components/component-library/checkbox/checkbox.test.tsx new file mode 100644 index 000000000..fb7983842 --- /dev/null +++ b/ui/components/component-library/checkbox/checkbox.test.tsx @@ -0,0 +1,182 @@ +import * as React from 'react'; +import { render, fireEvent } from '@testing-library/react'; +import { BorderColor } from '../../../helpers/constants/design-system'; +import { Checkbox } from '.'; + +describe('Checkbox', () => { + it('should render the Checkbox without crashing', () => { + const { getByRole, container } = render(); + expect(getByRole('checkbox')).toBeInTheDocument(); + expect(container).toMatchSnapshot(); + }); + + it('should render the Checkbox with additional className', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('classname')).toHaveClass('mm-checkbox mm-test'); + }); + + it('should render the Checkbox with additional className on the input', () => { + const { getByRole } = render( + , + ); + expect(getByRole('checkbox')).toHaveClass('mm-checkbox__input mm-test'); + }); + + it('should render the Checkbox with border color changed from inputProps', () => { + const { getByRole } = render( + , + ); + expect(getByRole('checkbox')).toHaveClass( + 'mm-box--border-color-error-default', + ); + }); + + it('should render isChecked', () => { + const { getByRole, getByTestId } = render( + , + ); + expect(getByRole('checkbox')).toBeChecked(); + expect(window.getComputedStyle(getByTestId('check-bold')).maskImage).toBe( + `url('./images/icons/check-bold.svg')`, + ); + }); + + it('should render isIndeterminate', () => { + const { getByRole, getByTestId } = render( + , + ); + expect(getByRole('checkbox').getAttribute('data-indeterminate')).toBe( + 'true', + ); + expect(window.getComputedStyle(getByTestId('minus-bold')).maskImage).toBe( + `url('./images/icons/minus-bold.svg')`, + ); + }); + + it('should render checkbox with label', () => { + const { getByText } = render(); + expect(getByText('Option 1')).toBeDefined(); + }); + + it('should render checkbox with id and label has matching htmlfor', () => { + const { getByTestId, getByRole } = render( + , + ); + const checkbox = getByRole('checkbox'); + + expect(checkbox).toHaveAttribute('id', 'option-1'); + expect(getByTestId('label')).toHaveAttribute('for', 'option-1'); + }); + + test('Checkbox component is disabled when isDisabled is true', () => { + const { getByRole, getByTestId } = render( + , + ); + + const checkbox = getByRole('checkbox'); + + expect(checkbox).toBeDisabled(); + expect(getByTestId('option-disabled')).toHaveClass('mm-checkbox--disabled'); + }); + + test('Checkbox component is readOnly when isReadOnly is true', () => { + const { getByLabelText } = render( + , + ); + + const checkbox = getByLabelText('Option 1'); + + expect(checkbox).toHaveAttribute('readonly'); + expect(checkbox).toHaveClass('mm-checkbox__input--readonly'); + }); + + it('Checkbox component fires onChange function when clicked', () => { + const onChange = jest.fn(); + + const { getByTestId } = render( + , + ); + + const checkbox = getByTestId('checkbox'); + + fireEvent.click(checkbox); + + expect(onChange).toHaveBeenCalled(); + }); + + it('Checkbox component fires onChange function label clicked', () => { + const onChange = jest.fn(); + + const { getByText } = render( + , + ); + + const label = getByText('Click label'); + + fireEvent.click(label); + + expect(onChange).toHaveBeenCalled(); + }); + + test('Checkbox component is required when isRequired is true', () => { + const { getByLabelText } = render( + , + ); + + const checkbox = getByLabelText('Option 1'); + + expect(checkbox).toHaveAttribute('required'); + }); + + test('Checkbox component renders with the correct title attribute', () => { + const { getByLabelText } = render( + , + ); + + const checkbox = getByLabelText('Option 1'); + + expect(checkbox).toHaveAttribute('title', 'pineapple'); + }); + + test('Checkbox component renders with the correct title attribute used from the label', () => { + const { getByLabelText } = render( + , + ); + + const checkbox = getByLabelText('Option 1'); + + expect(checkbox).toHaveAttribute('title', 'Option 1'); + }); + + test('Checkbox component renders with the correct title attribute used from the id', () => { + const { getByRole } = render(); + + const checkbox = getByRole('checkbox'); + + expect(checkbox).toHaveAttribute('title', 'option-1'); + }); + + test('Checkbox component renders with the correct name attribute', () => { + const { getByRole } = render(); + + const checkbox = getByRole('checkbox'); + + expect(checkbox).toHaveAttribute('name', 'option-1'); + }); +}); diff --git a/ui/components/component-library/checkbox/checkbox.tsx b/ui/components/component-library/checkbox/checkbox.tsx new file mode 100644 index 000000000..83d0a8113 --- /dev/null +++ b/ui/components/component-library/checkbox/checkbox.tsx @@ -0,0 +1,124 @@ +import React, { ChangeEvent, KeyboardEvent } from 'react'; +import classnames from 'classnames'; + +import { + BackgroundColor, + BorderColor, + BorderRadius, + IconColor, + Display, + AlignItems, +} from '../../../helpers/constants/design-system'; +import type { PolymorphicRef } from '../box'; + +import { Box, Icon, IconName, Text } from '..'; + +import { CheckboxProps, CheckboxComponent } from './checkbox.types'; + +export const Checkbox: CheckboxComponent = React.forwardRef( + ( + { + id, + isChecked, + isIndeterminate, + isDisabled, + isReadOnly, + isRequired, + onChange, + className = '', + iconProps, + inputProps, + inputRef, + title, + name, + label, + ...props + }: CheckboxProps, + ref?: PolymorphicRef, + ) => { + const handleCheckboxKeyDown = (event: KeyboardEvent) => { + if (event.key === 'Enter') { + onChange?.(event as unknown as ChangeEvent); + } + }; + + // If no title is provided, use the label as the title only if the label is a string + const sanitizedTitle = + !title && typeof label === 'string' ? label : title || id; + + return ( + + + ) => { + if (isReadOnly) { + event.preventDefault(); + } else { + onChange?.(event); + } + }} + onKeyDown={handleCheckboxKeyDown} + margin={0} + marginRight={label ? 2 : 0} + backgroundColor={ + isChecked || isIndeterminate + ? BackgroundColor.primaryDefault + : BackgroundColor.transparent + } + borderColor={ + isChecked || isIndeterminate + ? BorderColor.primaryDefault + : BorderColor.borderDefault + } + borderRadius={BorderRadius.SM} + borderWidth={2} + display={Display.Flex} + ref={inputRef} + {...inputProps} + className={classnames( + 'mm-checkbox__input', + inputProps?.className ?? '', + { + 'mm-checkbox__input--checked': Boolean(isChecked), + 'mm-checkbox__input--indeterminate': Boolean(isIndeterminate), + 'mm-checkbox__input--readonly': Boolean(isReadOnly), + }, + )} + /> + {(isChecked || isIndeterminate) && ( + + )} + + {label ? {label} : null} + + ); + }, +); diff --git a/ui/components/component-library/checkbox/checkbox.types.ts b/ui/components/component-library/checkbox/checkbox.types.ts new file mode 100644 index 000000000..cc7871b8c --- /dev/null +++ b/ui/components/component-library/checkbox/checkbox.types.ts @@ -0,0 +1,74 @@ +import { IconProps } from '../icon'; +import type { + StyleUtilityProps, + PolymorphicComponentPropWithRef, +} from '../box'; + +export interface CheckboxStyleUtilityProps extends StyleUtilityProps { + /* + * Additional classNames to be added to the Checkbox component + */ + className?: string; + /* + * id - the id for the Checkbox and used for the htmlFor attribute of the label + */ + id?: string; + /* + * isDisabled - if true, the Checkbox will be disabled + */ + isDisabled?: boolean; + /* + * isChecked - if true, the Checkbox will be checked + */ + isChecked?: boolean; + /* + * isIndeterminate - if true, the Checkbox will be indeterminate + */ + isIndeterminate?: boolean; + /* + * isReadOnly - if true, the Checkbox will be read only + */ + isReadOnly?: boolean; + /* + * isRequired - if true, the Checkbox will be required + */ + isRequired?: boolean; + /* + * title can help add additional context to the Checkbox for screen readers and will work for native tooltip elements + * if no title is passed, then it will try to use the label prop if it is a string + */ + title?: string; + /* + * name - to identify the checkbox and associate it with its value during form submission + */ + name?: string; + /* + * onChange - the function to call when the Checkbox is changed + */ + onChange?: (event: React.ChangeEvent) => void; + /* + * label is the string or ReactNode to be rendered next to the Checkbox + */ + label?: any; + /* + * Use inputProps for additional props to be spread to the checkbox input element + */ + inputProps?: any; // TODO: Replace with Box types when the syntax and typing is properly figured out. Needs to accept everything Box accepts + /* + * Use inputRef to pass a ref to the html input element + */ + inputRef?: + | React.RefObject + | ((instance: HTMLInputElement | null) => void); + /* + * iconProps - additional props to be spread to the Icon component used for the Checkbox + */ + iconProps?: IconProps; +} + +export type CheckboxProps = + PolymorphicComponentPropWithRef; + +export type CheckboxComponent = ( + props: CheckboxProps, +) => React.ReactElement | null; diff --git a/ui/components/component-library/checkbox/index.ts b/ui/components/component-library/checkbox/index.ts new file mode 100644 index 000000000..cf2067124 --- /dev/null +++ b/ui/components/component-library/checkbox/index.ts @@ -0,0 +1,2 @@ +export { Checkbox } from './checkbox'; +export type { CheckboxProps } from './checkbox.types'; diff --git a/ui/components/component-library/component-library-components.scss b/ui/components/component-library/component-library-components.scss index d03fb28f1..f6bbd81e4 100644 --- a/ui/components/component-library/component-library-components.scss +++ b/ui/components/component-library/component-library-components.scss @@ -27,6 +27,7 @@ @import 'button-link/button-link'; @import 'button-primary/button-primary'; @import 'button-secondary/button-secondary'; +@import 'checkbox/checkbox'; @import 'input/input'; // Molecules @import 'picker-network/picker-network'; diff --git a/ui/components/component-library/icon/icon.types.ts b/ui/components/component-library/icon/icon.types.ts index 011ca4700..1ad735719 100644 --- a/ui/components/component-library/icon/icon.types.ts +++ b/ui/components/component-library/icon/icon.types.ts @@ -44,6 +44,7 @@ export enum IconName { Card = 'card', Category = 'category', Chart = 'chart', + CheckBold = 'check-bold', Check = 'check', Clock = 'clock', Close = 'close', @@ -93,6 +94,7 @@ export enum IconName { Menu = 'menu', MessageQuestion = 'message-question', Messages = 'messages', + MinusBold = 'minus-bold', MinusSquare = 'minus-square', Minus = 'minus', Mobile = 'mobile', diff --git a/ui/components/component-library/index.js b/ui/components/component-library/index.js index 4da644ec7..564643063 100644 --- a/ui/components/component-library/index.js +++ b/ui/components/component-library/index.js @@ -21,6 +21,7 @@ export { ButtonIcon, ButtonIconSize } from './button-icon'; export { ButtonLink, BUTTON_LINK_SIZES } from './button-link'; export { ButtonPrimary, BUTTON_PRIMARY_SIZES } from './button-primary'; export { ButtonSecondary, BUTTON_SECONDARY_SIZES } from './button-secondary'; +export { Checkbox } from './checkbox'; export { FormTextField } from './form-text-field'; export { HeaderBase } from './header-base'; export { HelpText } from './help-text'; From c028bba8fd53025c05e604587fa850aa3f4a3632 Mon Sep 17 00:00:00 2001 From: Garrett Bear Date: Fri, 14 Jul 2023 12:25:46 -0700 Subject: [PATCH 054/172] Update ButtonLink hover underline (#19992) * Update ButtonLink hover underline * update buttonlink to use text decoration * update buttonlink to use text decoration * fix lint --- .../component-library/button-link/button-link.scss | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ui/components/component-library/button-link/button-link.scss b/ui/components/component-library/button-link/button-link.scss index 9d68e42d8..219ee938e 100644 --- a/ui/components/component-library/button-link/button-link.scss +++ b/ui/components/component-library/button-link/button-link.scss @@ -1,5 +1,10 @@ - .mm-button-link { + &:hover:not(&--disabled) { + text-decoration: underline; + text-decoration-thickness: 2px; + text-underline-offset: 4px; + } + &:active { color: var(--color-primary-alternative); } @@ -38,4 +43,9 @@ line-height: inherit; letter-spacing: inherit; } + + &--size-inherit:hover:not(&--disabled) { + text-decoration-thickness: auto; + text-underline-offset: 2px; + } } From 805cc31e638f13da412ed4a22cdbeacb9f58eb9d Mon Sep 17 00:00:00 2001 From: George Marshall Date: Fri, 14 Jul 2023 13:05:00 -0700 Subject: [PATCH 055/172] Updating BadgeWrapper to use TS Box (#19769) --- .../__snapshots__/nft-details.test.js.snap | 4 +- .../__snapshots__/token-cell.test.js.snap | 4 +- .../__snapshots__/badge-wrapper.test.tsx.snap | 4 +- .../badge-wrapper/badge-wrapper.test.tsx | 10 +-- .../badge-wrapper/badge-wrapper.tsx | 66 ++++++++++--------- .../badge-wrapper/badge-wrapper.types.ts | 26 ++++++-- .../connected-site-menu.test.js.snap | 12 ++-- .../token-list-item.test.js.snap | 4 +- 8 files changed, 74 insertions(+), 56 deletions(-) diff --git a/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap b/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap index ec9fd7afe..f2a08036e 100644 --- a/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap +++ b/ui/components/app/nft-details/__snapshots__/nft-details.test.js.snap @@ -50,7 +50,7 @@ exports[`NFT Details should match minimal props and state snapshot 1`] = ` data-testid="nft-item" >
MUNK #1 1
content
{ badge
} badgeContainerProps={{ 'data-testid': 'badge-custom' }} - position={{ - top: -10, - right: -10, + positionObj={{ + top: '-10px', + right: '-10px', }} > content custom @@ -108,8 +108,8 @@ describe('BadgeWrapper', () => { 'mm-badge-wrapper__badge-container--circular-top-right', ); expect(getByTestId('badge-custom')).toHaveStyle({ - top: -10, - right: -10, + top: '-10px', + right: '-10px', }); }); diff --git a/ui/components/component-library/badge-wrapper/badge-wrapper.tsx b/ui/components/component-library/badge-wrapper/badge-wrapper.tsx index b8ae0df7a..a566c2126 100644 --- a/ui/components/component-library/badge-wrapper/badge-wrapper.tsx +++ b/ui/components/component-library/badge-wrapper/badge-wrapper.tsx @@ -1,44 +1,50 @@ import React from 'react'; import classnames from 'classnames'; -import { DISPLAY } from '../../../helpers/constants/design-system'; - -import Box from '../../ui/box'; +import { Display } from '../../../helpers/constants/design-system'; +import { Box } from '..'; +import type { PolymorphicRef } from '../box'; import { BadgeWrapperPosition, BadgeWrapperAnchorElementShape, BadgeWrapperProps, + BadgeWrapperComponent, } from './badge-wrapper.types'; -export const BadgeWrapper = ({ - children, - badge, - badgeContainerProps, - position = BadgeWrapperPosition.topRight, - positionObj, - anchorElementShape = BadgeWrapperAnchorElementShape.circular, - className = '', - color, - ...props -}: BadgeWrapperProps) => ( - - {/* Generally the AvatarAccount or AvatarToken */} - {children} +export const BadgeWrapper: BadgeWrapperComponent = React.forwardRef( + ( + { + children, + badge, + badgeContainerProps, + position = BadgeWrapperPosition.topRight, + positionObj, + anchorElementShape = BadgeWrapperAnchorElementShape.circular, + className = '', + ...props + }: BadgeWrapperProps, + ref?: PolymorphicRef, + ) => ( - {/* Generally the AvatarNetwork at SIZES.XS */} - {badge} + {/* Generally the AvatarAccount or AvatarToken */} + {children} + + {/* Generally the AvatarNetwork at SIZES.XS */} + {badge} + - + ), ); diff --git a/ui/components/component-library/badge-wrapper/badge-wrapper.types.ts b/ui/components/component-library/badge-wrapper/badge-wrapper.types.ts index 3ff416c02..2bd65452f 100644 --- a/ui/components/component-library/badge-wrapper/badge-wrapper.types.ts +++ b/ui/components/component-library/badge-wrapper/badge-wrapper.types.ts @@ -1,4 +1,9 @@ -import type { BoxProps } from '../../ui/box/box.d'; +import React from 'react'; + +import type { + StyleUtilityProps, + PolymorphicComponentPropWithRef, +} from '../box'; export enum BadgeWrapperPosition { topRight = 'top-right', @@ -12,7 +17,7 @@ export enum BadgeWrapperAnchorElementShape { circular = 'circular', } -export interface BadgeWrapperProps extends BoxProps { +export interface BadgeWrapperStyleUtilityProps extends StyleUtilityProps { /** * The element to be wrapped by the BadgeWrapper and for the badge to be positioned on top of */ @@ -24,7 +29,7 @@ export interface BadgeWrapperProps extends BoxProps { /** * The BadgeWrapper props of the component. All Box props can be used */ - badgeContainerProps?: BoxProps; + badgeContainerProps?: any; // TODO: Replace with Box types when the syntax and typing is properly figured out. Needs to accept everything Box accepts /** * The position of the Badge. Possible values could be 'BadgeWrapperPosition.topRight', 'BadgeWrapperPosition.bottomRight','BadgeWrapperPosition.topLeft', 'BadgeWrapperPosition.bottomLeft' * Defaults to 'BadgeWrapperPosition.topRight' @@ -34,10 +39,10 @@ export interface BadgeWrapperProps extends BoxProps { * The positionObj can be used to override the default positioning of the badge it accepts an object with the following keys { top, right, bottom, left } */ positionObj?: { - top?: number; - right?: number; - bottom?: number; - left?: number; + top?: number | string; + right?: number | string; + bottom?: number | string; + left?: number | string; }; /** * The shape of the anchor element. Possible values could be 'BadgeWrapperAnchorElementShape.circular', 'BadgeWrapperAnchorElementShape.square' @@ -49,3 +54,10 @@ export interface BadgeWrapperProps extends BoxProps { */ className?: string; } + +export type BadgeWrapperProps = + PolymorphicComponentPropWithRef; + +export type BadgeWrapperComponent = ( + props: BadgeWrapperProps, +) => React.ReactElement | null; diff --git a/ui/components/multichain/connected-site-menu/__snapshots__/connected-site-menu.test.js.snap b/ui/components/multichain/connected-site-menu/__snapshots__/connected-site-menu.test.js.snap index b85220409..372d90b6f 100644 --- a/ui/components/multichain/connected-site-menu/__snapshots__/connected-site-menu.test.js.snap +++ b/ui/components/multichain/connected-site-menu/__snapshots__/connected-site-menu.test.js.snap @@ -16,14 +16,14 @@ exports[`Connected Site Menu should render the site menu in connected state 1`] tabindex="0" >
Date: Mon, 17 Jul 2023 12:11:38 +0200 Subject: [PATCH 056/172] =?UTF-8?q?[MMI]=C2=A0Fixed=20remove=20custodian?= =?UTF-8?q?=20token=20(#20021)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/scripts/controllers/mmi-controller.js | 21 +-- .../__snapshots__/checkbox.test.tsx.snap | 2 +- .../confirm-remove-jwt-modal.test.js.snap | 154 +----------------- .../confirm-remove-jwt-modal.js | 113 ++++++++----- .../confirm-remove-jwt-modal.stories.js | 2 +- .../confirm-remove-jwt-modal.test.js | 11 +- .../confirm-remove-jwt-modal/index.scss | 1 + ...eractive-replacement-token-notification.js | 2 +- .../account-list-item-menu.js | 4 +- ui/pages/institutional/custody/custody.js | 6 +- 10 files changed, 86 insertions(+), 230 deletions(-) diff --git a/app/scripts/controllers/mmi-controller.js b/app/scripts/controllers/mmi-controller.js index 8923487b5..0ed4deaae 100644 --- a/app/scripts/controllers/mmi-controller.js +++ b/app/scripts/controllers/mmi-controller.js @@ -442,25 +442,8 @@ export default class MMIController extends EventEmitter { return keyring.getTransactionDeepLink(from, custodyTxId); } - async getCustodianToken(custodianType) { - let currentCustodyType; - - const address = this.preferencesController.getSelectedAddress(); - - if (!custodianType) { - const resultCustody = this.custodyController.getCustodyTypeByAddress( - toChecksumHexAddress(address), - ); - currentCustodyType = resultCustody; - } - let keyring = await this.keyringController.getKeyringsByType( - currentCustodyType || `Custody - ${custodianType}`, - )[0]; - if (!keyring) { - keyring = await this.keyringController.addNewKeyring( - currentCustodyType || `Custody - ${custodianType}`, - ); - } + async getCustodianToken(address) { + const keyring = await this.keyringController.getKeyringForAccount(address); const { authDetails } = keyring.getAccountDetails(address); return keyring ? authDetails.jwt || authDetails.refreshToken : ''; } diff --git a/ui/components/component-library/checkbox/__snapshots__/checkbox.test.tsx.snap b/ui/components/component-library/checkbox/__snapshots__/checkbox.test.tsx.snap index 5df6da8de..90c0f27f5 100644 --- a/ui/components/component-library/checkbox/__snapshots__/checkbox.test.tsx.snap +++ b/ui/components/component-library/checkbox/__snapshots__/checkbox.test.tsx.snap @@ -3,7 +3,7 @@ exports[`Checkbox should render the Checkbox without crashing 1`] = `

diff --git a/ui/components/multichain/token-list-item/token-list-item.js b/ui/components/multichain/token-list-item/token-list-item.js index 5fdf36d59..dfdce0baf 100644 --- a/ui/components/multichain/token-list-item/token-list-item.js +++ b/ui/components/multichain/token-list-item/token-list-item.js @@ -19,8 +19,8 @@ import { AvatarToken, BadgeWrapper, Box, + Text, } from '../../component-library'; -import { Text } from '../../component-library/text/deprecated'; import { getCurrentChainId, getCurrentNetwork, From 1277c6225d345188db81386c93e20eee6e588a90 Mon Sep 17 00:00:00 2001 From: Harsh Shukla <125105825+PrgrmrHarshShukla@users.noreply.github.com> Date: Tue, 18 Jul 2023 10:33:46 +0530 Subject: [PATCH 066/172] Part of #18714 in ui\components\app\custom-spending-cap (#20039) * Part of #18714 in ui\components\app\custom-spending-cap * Update checkbox.test.tsx.snap --- .../custom-spending-cap/custom-spending-cap-tooltip.js | 4 ++-- .../app/custom-spending-cap/custom-spending-cap.js | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ui/components/app/custom-spending-cap/custom-spending-cap-tooltip.js b/ui/components/app/custom-spending-cap/custom-spending-cap-tooltip.js index a35e1a0f9..a08442bd3 100644 --- a/ui/components/app/custom-spending-cap/custom-spending-cap-tooltip.js +++ b/ui/components/app/custom-spending-cap/custom-spending-cap-tooltip.js @@ -4,8 +4,8 @@ import Box from '../../ui/box'; import Tooltip from '../../ui/tooltip'; import { TextColor, - DISPLAY, TextVariant, + Display, } from '../../../helpers/constants/design-system'; import { Icon, IconName, IconSize } from '../../component-library'; @@ -15,7 +15,7 @@ export const CustomSpendingCapTooltip = ({ tooltipContentText, tooltipIcon, }) => ( - +