diff --git a/.yarn/patches/@metamask-signature-controller-npm-4.0.1-013e64c9fd.patch b/.yarn/patches/@metamask-signature-controller-npm-4.0.1-013e64c9fd.patch deleted file mode 100644 index ef3f75e9e2c5..000000000000 --- a/.yarn/patches/@metamask-signature-controller-npm-4.0.1-013e64c9fd.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff --git a/dist/SignatureController.js b/dist/SignatureController.js -index b58b27e84aa84393afb366d4585c084d0380d21d..0629bcf517db744ccfa40e4d7d8f2829fa95559e 100644 ---- a/dist/SignatureController.js -+++ b/dist/SignatureController.js -@@ -237,8 +237,11 @@ _SignatureController_keyringController = new WeakMap(), _SignatureController_isE - yield __classPrivateFieldGet(this, _SignatureController_instances, "m", _SignatureController_requestApproval).call(this, messageParamsWithId, approvalType); - } - catch (error) { -+ signaturePromise.catch(() => { -+ // Expecting reject error but throwing manually rather than waiting -+ }); - __classPrivateFieldGet(this, _SignatureController_instances, "m", _SignatureController_cancelAbstractMessage).call(this, messageManager, messageId); -- throw eth_rpc_errors_1.ethErrors.provider.userRejectedRequest('User rejected the request.'); -+ throw eth_rpc_errors_1.ethErrors.provider.userRejectedRequest(`MetaMask ${messageName} Signature: User denied message signature.`); - } - yield signMessage(messageParamsWithId, version, signingOpts); - return signaturePromise; diff --git a/.yarn/patches/@metamask-signature-controller-npm-5.3.0-225628460b.patch b/.yarn/patches/@metamask-signature-controller-npm-5.3.0-225628460b.patch new file mode 100644 index 000000000000..ac03757638a0 --- /dev/null +++ b/.yarn/patches/@metamask-signature-controller-npm-5.3.0-225628460b.patch @@ -0,0 +1,26 @@ +diff --git a/dist/SignatureController.js b/dist/SignatureController.js +index a2f064efa2a2700db00767daa4ce6bd22b1932c4..17edb51b6c526f27fb4c19f2d2fda3d7140c66b4 100644 +--- a/dist/SignatureController.js ++++ b/dist/SignatureController.js +@@ -283,8 +283,11 @@ _SignatureController_keyringController = new WeakMap(), _SignatureController_isE + resultCallbacks = acceptResult.resultCallbacks; + } + catch (_a) { ++ signaturePromise.catch(() => { ++ // Expecting reject error but throwing manually rather than waiting ++ }); + __classPrivateFieldGet(this, _SignatureController_instances, "m", _SignatureController_cancelAbstractMessage).call(this, messageManager, messageId); +- throw eth_rpc_errors_1.ethErrors.provider.userRejectedRequest('User rejected the request.'); ++ throw eth_rpc_errors_1.ethErrors.provider.userRejectedRequest(`MetaMask ${messageName} Signature: User denied message signature.`); + } + yield signMessage(messageParamsWithId, signingOpts); + const signatureResult = yield signaturePromise; +@@ -305,7 +308,7 @@ _SignatureController_keyringController = new WeakMap(), _SignatureController_isE + return __awaiter(this, void 0, void 0, function* () { + return yield __classPrivateFieldGet(this, _SignatureController_instances, "m", _SignatureController_signAbstractMessage).call(this, __classPrivateFieldGet(this, _SignatureController_personalMessageManager, "f"), controller_utils_1.ApprovalType.PersonalSign, msgParams, (cleanMsgParams) => __awaiter(this, void 0, void 0, function* () { return yield __classPrivateFieldGet(this, _SignatureController_keyringController, "f").signPersonalMessage(cleanMsgParams); })); + }); +-}, _SignatureController_signTypedMessage = function _SignatureController_signTypedMessage(msgParams, ++}, _SignatureController_signTypedMessage = function _SignatureController_signTypedMessage(msgParams, + /* istanbul ignore next */ + opts = { parseJsonData: true }) { + return __awaiter(this, void 0, void 0, function* () { diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 995a0c34ef71..de66494e2daf 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -565,6 +565,30 @@ "blockaid": { "message": "Blockaid" }, + "blockaidDescriptionApproveFarming": { + "message": "If you approve this request, a third party known for scams might take all your assets." + }, + "blockaidDescriptionBlurFarming": { + "message": "If you approve this request, someone can steal your assets listed on Blur." + }, + "blockaidDescriptionMaliciousDomain": { + "message": "You're interacting with a malicious domain. If you approve this request, you might lose your assets." + }, + "blockaidDescriptionMightLoseAssets": { + "message": "If you approve this request, you might lose your assets." + }, + "blockaidDescriptionSeaportFarming": { + "message": "If you approve this request, someone can steal your assets listed on OpenSea." + }, + "blockaidDescriptionTransferFarming": { + "message": "If you approve this request, a third party known for scams will take all your assets." + }, + "blockaidTitleDeceptive": { + "message": "This is a deceptive request" + }, + "blockaidTitleSuspicious": { + "message": "This is a suspicious request" + }, "blockies": { "message": "Blockies" }, @@ -3579,6 +3603,13 @@ "securityAndPrivacy": { "message": "Security & privacy" }, + "securityProviderAdviceBy": { + "message": "Security advice by $1", + "description": "The security provider that is providing data" + }, + "seeDetails": { + "message": "See details" + }, "seedPhraseConfirm": { "message": "Confirm Secret Recovery Phrase" }, diff --git a/app/scripts/controllers/mmi-controller.js b/app/scripts/controllers/mmi-controller.js index 04694b716fde..ec7d999bb448 100644 --- a/app/scripts/controllers/mmi-controller.js +++ b/app/scripts/controllers/mmi-controller.js @@ -2,10 +2,6 @@ import EventEmitter from 'events'; import log from 'loglevel'; import { captureException } from '@sentry/browser'; import { isEqual } from 'lodash'; -import { - PersonalMessageManager, - TypedMessageManager, -} from '@metamask/message-manager'; import { CUSTODIAN_TYPES } from '@metamask-institutional/custody-keyring'; import { updateCustodianTransactions, @@ -48,20 +44,10 @@ export default class MMIController extends EventEmitter { this.metaMetricsController = opts.metaMetricsController; this.networkController = opts.networkController; this.permissionController = opts.permissionController; + this.signatureController = opts.signatureController; this.platform = opts.platform; this.extension = opts.extension; - this.personalMessageManager = new PersonalMessageManager( - undefined, - undefined, - this.securityProviderRequest, - ); - this.typedMessageManager = new TypedMessageManager( - undefined, - undefined, - this.securityProviderRequest, - ); - // Prepare event listener after transactionUpdateController gets initiated this.transactionUpdateController.prepareEventListener( this.custodianEventHandlerFactory.bind(this), @@ -87,6 +73,20 @@ export default class MMIController extends EventEmitter { await this.prepareMmiPortfolio(); }, this.preferencesController.store.getState()), ); + + this.signatureController.hub.on( + 'personal_sign:signed', + async ({ signature, messageId }) => { + await this.handleSigningEvents(signature, messageId, 'personal'); + }, + ); + + this.signatureController.hub.on( + 'eth_signTypedData:signed', + async ({ signature, messageId }) => { + await this.handleSigningEvents(signature, messageId, 'v4'); + }, + ); } // End of constructor async persistKeyringsAfterRefreshTokenChange() { @@ -111,8 +111,7 @@ export default class MMIController extends EventEmitter { getState: () => this.getState(), getPendingNonce: (address) => this.getPendingNonce(address), setTxHash: (txId, txHash) => this.txController.setTxHash(txId, txHash), - typedMessageManager: this.typedMessageManager, - personalMessageManager: this.personalMessageManager, + signatureController: this.signatureController, txStateManager: this.txController.txStateManager, custodyController: this.custodyController, trackTransactionEvent: @@ -185,9 +184,10 @@ export default class MMIController extends EventEmitter { keyring, type, txList, - getPendingNonce: this.getPendingNonce.bind(this), + getPendingNonce: (address) => this.getPendingNonce(address), + setTxHash: (txId, txHash) => + this.txController.setTxHash(txId, txHash), txStateManager: this.txController.txStateManager, - setTxHash: this.txController.setTxHash.bind(this.txController), custodyController: this.custodyController, transactionUpdateController: this.transactionUpdateController, }); @@ -572,6 +572,42 @@ export default class MMIController extends EventEmitter { } } + async newUnsignedMessage(msgParams, req, version) { + const updatedMsgParams = { ...msgParams, deferSetAsSigned: true }; + + if (req.method.includes('eth_signTypedData')) { + return await this.signatureController.newUnsignedTypedMessage( + updatedMsgParams, + req, + version, + ); + } else if (req.method.includes('personal_sign')) { + return await this.signatureController.newUnsignedPersonalMessage( + updatedMsgParams, + req, + ); + } + return await this.signatureController.newUnsignedMessage( + updatedMsgParams, + req, + ); + } + + async handleSigningEvents(signature, messageId, signOperation) { + if (signature.custodian_transactionId) { + this.transactionUpdateController.addTransactionToWatchList( + signature.custodian_transactionId, + signature.from, + signOperation, + true, + ); + } + + this.signatureController.setMessageMetadata(messageId, signature); + + return this.getState(); + } + async setAccountAndNetwork(origin, address, chainId) { await this.appStateController.getUnlockPromise(true); const selectedAddress = this.preferencesController.getSelectedAddress(); diff --git a/app/scripts/controllers/mmi-controller.test.js b/app/scripts/controllers/mmi-controller.test.js index f6f9cc5f786c..de06940c8a5f 100644 --- a/app/scripts/controllers/mmi-controller.test.js +++ b/app/scripts/controllers/mmi-controller.test.js @@ -2,6 +2,7 @@ import { KeyringController } from '@metamask/eth-keyring-controller'; import { MmiConfigurationController } from '@metamask-institutional/custody-keyring'; import { TransactionUpdateController } from '@metamask-institutional/transaction-update'; +import { SignatureController } from '@metamask/signature-controller'; import MMIController from './mmi-controller'; import TransactionController from './transactions'; @@ -33,6 +34,20 @@ describe('MMIController', function () { getNetworkId: jest.fn(), onNetworkStateChange: jest.fn(), }), + signatureController: new SignatureController({ + messenger: { + registerActionHandler: jest.fn(), + publish: jest.fn(), + call: jest.fn(), + }, + keyringController: new KeyringController({ + initState: {}, + }), + isEthSignEnabled: jest.fn(), + getAllState: jest.fn(), + securityProviderRequest: jest.fn(), + getCurrentChainId: jest.fn(), + }), preferencesController: new PreferencesController({ initState: {}, onInfuraIsBlocked: jest.fn(), diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index a383f8221dfa..bac3c79ce371 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -352,6 +352,6 @@ function toMetamaskUrl(origUrl) { if (!filePath) { return origUrl; } - const metamaskUrl = `metamask${filePath}`; + const metamaskUrl = `/metamask${filePath}`; return metamaskUrl; } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 928cdae589fc..9ee6bd147d7f 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -499,16 +499,14 @@ export default class MetamaskController extends EventEmitter { this.metaMetricsController.trackEvent({ event: MetaMetricsEventName.NftAdded, category: MetaMetricsEventCategory.Wallet, - properties: { + sensitiveProperties: { token_contract_address: address, token_symbol: symbol, - asset_type: AssetType.NFT, + token_id: tokenId, token_standard: standard, + asset_type: AssetType.NFT, source, }, - sensitiveProperties: { - tokenId, - }, }), }, {}, @@ -1196,28 +1194,6 @@ export default class MetamaskController extends EventEmitter { }), }); - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - this.mmiController = new MMIController({ - mmiConfigurationController: this.mmiConfigurationController, - keyringController: this.keyringController, - txController: this.txController, - securityProviderRequest: this.securityProviderRequest.bind(this), - preferencesController: this.preferencesController, - appStateController: this.appStateController, - transactionUpdateController: this.transactionUpdateController, - custodyController: this.custodyController, - institutionalFeaturesController: this.institutionalFeaturesController, - getState: this.getState.bind(this), - getPendingNonce: this.getPendingNonce.bind(this), - accountTracker: this.accountTracker, - metaMetricsController: this.metaMetricsController, - networkController: this.networkController, - permissionController: this.permissionController, - platform: this.platform, - extension: this.extension, - }); - ///: END:ONLY_INCLUDE_IN - this.txController.on(`tx:status-update`, async (txId, status) => { if ( status === TransactionStatus.confirmed || @@ -1379,6 +1355,29 @@ export default class MetamaskController extends EventEmitter { }, ); + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + this.mmiController = new MMIController({ + mmiConfigurationController: this.mmiConfigurationController, + keyringController: this.keyringController, + txController: this.txController, + securityProviderRequest: this.securityProviderRequest.bind(this), + preferencesController: this.preferencesController, + appStateController: this.appStateController, + transactionUpdateController: this.transactionUpdateController, + custodyController: this.custodyController, + institutionalFeaturesController: this.institutionalFeaturesController, + getState: this.getState.bind(this), + getPendingNonce: this.getPendingNonce.bind(this), + accountTracker: this.accountTracker, + metaMetricsController: this.metaMetricsController, + networkController: this.networkController, + permissionController: this.permissionController, + signatureController: this.signatureController, + platform: this.platform, + extension: this.extension, + }); + ///: END:ONLY_INCLUDE_IN + this.swapsController = new SwapsController( { getBufferedGasLimit: @@ -1496,6 +1495,7 @@ export default class MetamaskController extends EventEmitter { // tx signing processTransaction: this.newUnapprovedTransaction.bind(this), // msg signing + ///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask) processEthSignMessage: this.signatureController.newUnsignedMessage.bind( this.signatureController, ), @@ -1515,8 +1515,25 @@ export default class MetamaskController extends EventEmitter { this.signatureController.newUnsignedPersonalMessage.bind( this.signatureController, ), + ///: END:ONLY_INCLUDE_IN ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + /* eslint-disable no-dupe-keys */ + processEthSignMessage: this.mmiController.newUnsignedMessage.bind( + this.mmiController, + ), + processTypedMessage: this.mmiController.newUnsignedMessage.bind( + this.mmiController, + ), + processTypedMessageV3: this.mmiController.newUnsignedMessage.bind( + this.mmiController, + ), + processTypedMessageV4: this.mmiController.newUnsignedMessage.bind( + this.mmiController, + ), + processPersonalMessage: this.mmiController.newUnsignedMessage.bind( + this.mmiController, + ), setTypedMessageInProgress: this.signatureController.setTypedMessageInProgress.bind( this.signatureController, @@ -1525,6 +1542,7 @@ export default class MetamaskController extends EventEmitter { this.signatureController.setPersonalMessageInProgress.bind( this.signatureController, ), + /* eslint-enable no-dupe-keys */ ///: END:ONLY_INCLUDE_IN processEncryptionPublicKey: diff --git a/development/build/index.js b/development/build/index.js index 84ee91040278..92a6ea678d60 100755 --- a/development/build/index.js +++ b/development/build/index.js @@ -99,6 +99,8 @@ async function defineAndRunBuildTasks() { 'navigator', 'harden', 'console', + 'WeakSet', + 'Event', 'Image', // Used by browser to generate notifications // globals chromedriver needs to function /cdc_[a-zA-Z0-9]+_[a-zA-Z]+/iu, diff --git a/development/sentry-upload-artifacts.sh b/development/sentry-upload-artifacts.sh index 9d2fd32b4262..e70989123e03 100755 --- a/development/sentry-upload-artifacts.sh +++ b/development/sentry-upload-artifacts.sh @@ -31,7 +31,7 @@ function upload_sourcemaps { local release="${1}"; shift local dist_directory="${1}"; shift - sentry-cli releases files "${release}" upload-sourcemaps "${dist_directory}"/chrome/*.js "${dist_directory}"/sourcemaps/ --rewrite --url-prefix 'metamask' + sentry-cli releases files "${release}" upload-sourcemaps "${dist_directory}"/chrome/*.js "${dist_directory}"/sourcemaps/ --rewrite --url-prefix '/metamask' } function main { diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index 3afc49c783b8..0ac70c31e4a4 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -173,29 +173,13 @@ "packages": { "@ethereumjs/tx>@chainsafe/ssz": true, "@ethereumjs/tx>@ethereumjs/rlp": true, - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography": true, "@ethereumjs/tx>@ethereumjs/util>micro-ftch": true, + "@ethereumjs/tx>ethereum-cryptography": true, "browserify>buffer": true, "browserify>events": true, "browserify>insert-module-globals>is-buffer": true } }, - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography": { - "globals": { - "TextDecoder": true, - "crypto": true - }, - "packages": { - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography>@noble/hashes": true, - "@ethereumjs/tx>ethereum-cryptography>@noble/curves": true - } - }, - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography>@noble/hashes": { - "globals": { - "TextEncoder": true, - "crypto": true - } - }, "@ethereumjs/tx>@ethereumjs/util>micro-ftch": { "globals": { "Headers": true, @@ -220,6 +204,7 @@ "crypto": true }, "packages": { + "@ethereumjs/tx>ethereum-cryptography>@noble/curves": true, "@ethereumjs/tx>ethereum-cryptography>@noble/hashes": true } }, @@ -887,8 +872,8 @@ "setTimeout": true }, "packages": { + "@metamask/controller-utils>@metamask/utils": true, "@metamask/controller-utils>@spruceid/siwe-parser": true, - "@metamask/utils": true, "browserify>buffer": true, "eslint>fast-deep-equal": true, "eth-ens-namehash": true, @@ -896,6 +881,19 @@ "ethjs>ethjs-unit": true } }, + "@metamask/controller-utils>@metamask/utils": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "@metamask/key-tree>@noble/hashes": true, + "browserify>buffer": true, + "nock>debug": true, + "semver": true, + "superstruct": true + } + }, "@metamask/controller-utils>@spruceid/siwe-parser": { "globals": { "console.error": true, @@ -1025,9 +1023,9 @@ "packages": { "@ethereumjs/tx>@ethereumjs/util": true, "@metamask/eth-keyring-controller>@metamask/eth-sig-util>ethereum-cryptography": true, - "@metamask/eth-keyring-controller>@metamask/eth-sig-util>ethjs-util": true, "bn.js": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "eth-sig-util>tweetnacl": true, "eth-sig-util>tweetnacl-util": true } @@ -1047,13 +1045,6 @@ "crypto": true } }, - "@metamask/eth-keyring-controller>@metamask/eth-sig-util>ethjs-util": { - "packages": { - "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true - } - }, "@metamask/eth-keyring-controller>@metamask/eth-simple-keyring": { "packages": { "@ethereumjs/tx>@ethereumjs/util": true, @@ -1114,22 +1105,23 @@ }, "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util": { "packages": { - "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethjs-util": true, + "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethereum-cryptography": true, "bn.js": true, "browserify>assert": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, "ethereumjs-wallet>safe-buffer": true, "ganache>secp256k1>elliptic": true } }, - "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethjs-util": { + "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethereum-cryptography": { "packages": { "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true } }, "@metamask/eth-ledger-bridge-keyring>hdkey": { @@ -1154,36 +1146,14 @@ "@metamask/eth-snap-keyring>@metamask/eth-sig-util": { "packages": { "@ethereumjs/tx>@ethereumjs/util": true, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography": true, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethjs-util": true, + "@ethereumjs/tx>ethereum-cryptography": true, "bn.js": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "eth-sig-util>tweetnacl": true, "eth-sig-util>tweetnacl-util": true } }, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography": { - "globals": { - "TextDecoder": true, - "crypto": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography>@noble/hashes": true - } - }, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography>@noble/hashes": { - "globals": { - "TextEncoder": true, - "crypto": true - } - }, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethjs-util": { - "packages": { - "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true - } - }, "@metamask/eth-token-tracker": { "globals": { "console.warn": true @@ -1242,11 +1212,11 @@ "@metamask/eth-token-tracker>ethjs>ethjs-abi": true, "@metamask/eth-token-tracker>ethjs>ethjs-contract": true, "@metamask/eth-token-tracker>ethjs>ethjs-query": true, + "@metamask/eth-token-tracker>ethjs>ethjs-util": true, "browserify>buffer": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-provider-http": true, "ethjs>ethjs-unit": true, - "ethjs>ethjs-util": true, "ethjs>js-sha3": true, "ethjs>number-to-bn": true } @@ -1262,9 +1232,9 @@ "@metamask/eth-token-tracker>ethjs>ethjs-contract": { "packages": { "@metamask/eth-token-tracker>ethjs>ethjs-contract>ethjs-abi": true, + "@metamask/eth-token-tracker>ethjs>ethjs-util": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, - "ethjs>ethjs-util": true, "ethjs>js-sha3": true, "promise-to-callback": true } @@ -1288,6 +1258,13 @@ "promise-to-callback": true } }, + "@metamask/eth-token-tracker>ethjs>ethjs-util": { + "packages": { + "browserify>buffer": true, + "ethjs>ethjs-util>is-hex-prefixed": true, + "ethjs>ethjs-util>strip-hex-prefix": true + } + }, "@metamask/eth-token-tracker>safe-event-emitter": { "globals": { "setTimeout": true @@ -1565,14 +1542,25 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, + "@metamask/message-manager>@metamask/eth-sig-util": true, "@metamask/message-manager>jsonschema": true, "browserify>buffer": true, "browserify>events": true, - "eth-sig-util": true, "ethereumjs-util": true, "uuid": true } }, + "@metamask/message-manager>@metamask/eth-sig-util": { + "packages": { + "@ethereumjs/tx>@ethereumjs/util": true, + "@ethereumjs/tx>ethereum-cryptography": true, + "bn.js": true, + "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, + "eth-sig-util>tweetnacl": true, + "eth-sig-util>tweetnacl-util": true + } + }, "@metamask/message-manager>jsonschema": { "packages": { "browserify>url": true @@ -3481,14 +3469,22 @@ "bn.js": true, "browserify>assert": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethereum-cryptography": true, "eth-sig-util>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, "ethereumjs-wallet>safe-buffer": true, "ganache>secp256k1>elliptic": true } }, + "eth-sig-util>ethereumjs-util>ethereum-cryptography": { + "packages": { + "browserify>buffer": true, + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true + } + }, "eth-sig-util>ethereumjs-util>ethjs-util": { "packages": { "browserify>buffer": true, @@ -3527,18 +3523,19 @@ "bn.js": true, "browserify>assert": true, "browserify>buffer": true, - "ethereumjs-abi>ethereumjs-util>ethjs-util": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, + "ethereumjs-abi>ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, "ganache>secp256k1>elliptic": true } }, - "ethereumjs-abi>ethereumjs-util>ethjs-util": { + "ethereumjs-abi>ethereumjs-util>ethereum-cryptography": { "packages": { "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true } }, "ethereumjs-util": { @@ -3718,25 +3715,26 @@ "ethereumjs-wallet>safe-buffer": true } }, + "ethereumjs-wallet>ethereum-cryptography": { + "packages": { + "browserify>buffer": true, + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true + } + }, "ethereumjs-wallet>ethereumjs-util": { "packages": { "bn.js": true, "browserify>assert": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>ethereumjs-util>ethjs-util": true, + "ethereumjs-wallet>ethereum-cryptography": true, "ganache>secp256k1>elliptic": true } }, - "ethereumjs-wallet>ethereumjs-util>ethjs-util": { - "packages": { - "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true - } - }, "ethereumjs-wallet>randombytes": { "globals": { "crypto": true, @@ -3791,9 +3789,9 @@ "ethjs-contract": { "packages": { "ethjs-contract>ethjs-abi": true, + "ethjs-contract>ethjs-util": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, - "ethjs>ethjs-util": true, "ethjs>js-sha3": true, "promise-to-callback": true } @@ -3806,6 +3804,13 @@ "ethjs>number-to-bn": true } }, + "ethjs-contract>ethjs-util": { + "packages": { + "browserify>buffer": true, + "ethjs>ethjs-util>is-hex-prefixed": true, + "ethjs>ethjs-util>strip-hex-prefix": true + } + }, "ethjs-query": { "globals": { "console": true @@ -3836,11 +3841,18 @@ "ethjs-query>ethjs-format": { "packages": { "ethjs-query>ethjs-format>ethjs-schema": true, - "ethjs>ethjs-util": true, + "ethjs-query>ethjs-format>ethjs-util": true, "ethjs>ethjs-util>strip-hex-prefix": true, "ethjs>number-to-bn": true } }, + "ethjs-query>ethjs-format>ethjs-util": { + "packages": { + "browserify>buffer": true, + "ethjs>ethjs-util>is-hex-prefixed": true, + "ethjs>ethjs-util>strip-hex-prefix": true + } + }, "ethjs-query>ethjs-rpc": { "packages": { "promise-to-callback": true diff --git a/lavamoat/browserify/desktop/policy.json b/lavamoat/browserify/desktop/policy.json index 682b9ad41f31..4f181ab36329 100644 --- a/lavamoat/browserify/desktop/policy.json +++ b/lavamoat/browserify/desktop/policy.json @@ -173,29 +173,13 @@ "packages": { "@ethereumjs/tx>@chainsafe/ssz": true, "@ethereumjs/tx>@ethereumjs/rlp": true, - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography": true, "@ethereumjs/tx>@ethereumjs/util>micro-ftch": true, + "@ethereumjs/tx>ethereum-cryptography": true, "browserify>buffer": true, "browserify>events": true, "browserify>insert-module-globals>is-buffer": true } }, - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography": { - "globals": { - "TextDecoder": true, - "crypto": true - }, - "packages": { - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography>@noble/hashes": true, - "@ethereumjs/tx>ethereum-cryptography>@noble/curves": true - } - }, - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography>@noble/hashes": { - "globals": { - "TextEncoder": true, - "crypto": true - } - }, "@ethereumjs/tx>@ethereumjs/util>micro-ftch": { "globals": { "Headers": true, @@ -220,6 +204,7 @@ "crypto": true }, "packages": { + "@ethereumjs/tx>ethereum-cryptography>@noble/curves": true, "@ethereumjs/tx>ethereum-cryptography>@noble/hashes": true } }, @@ -887,8 +872,8 @@ "setTimeout": true }, "packages": { + "@metamask/controller-utils>@metamask/utils": true, "@metamask/controller-utils>@spruceid/siwe-parser": true, - "@metamask/utils": true, "browserify>buffer": true, "eslint>fast-deep-equal": true, "eth-ens-namehash": true, @@ -896,6 +881,19 @@ "ethjs>ethjs-unit": true } }, + "@metamask/controller-utils>@metamask/utils": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "@metamask/key-tree>@noble/hashes": true, + "browserify>buffer": true, + "nock>debug": true, + "semver": true, + "superstruct": true + } + }, "@metamask/controller-utils>@spruceid/siwe-parser": { "globals": { "console.error": true, @@ -1096,9 +1094,9 @@ "packages": { "@ethereumjs/tx>@ethereumjs/util": true, "@metamask/eth-keyring-controller>@metamask/eth-sig-util>ethereum-cryptography": true, - "@metamask/eth-keyring-controller>@metamask/eth-sig-util>ethjs-util": true, "bn.js": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "eth-sig-util>tweetnacl": true, "eth-sig-util>tweetnacl-util": true } @@ -1118,13 +1116,6 @@ "crypto": true } }, - "@metamask/eth-keyring-controller>@metamask/eth-sig-util>ethjs-util": { - "packages": { - "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true - } - }, "@metamask/eth-keyring-controller>@metamask/eth-simple-keyring": { "packages": { "@ethereumjs/tx>@ethereumjs/util": true, @@ -1185,22 +1176,23 @@ }, "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util": { "packages": { - "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethjs-util": true, + "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethereum-cryptography": true, "bn.js": true, "browserify>assert": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, "ethereumjs-wallet>safe-buffer": true, "ganache>secp256k1>elliptic": true } }, - "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethjs-util": { + "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethereum-cryptography": { "packages": { "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true } }, "@metamask/eth-ledger-bridge-keyring>hdkey": { @@ -1239,36 +1231,14 @@ "@metamask/eth-snap-keyring>@metamask/eth-sig-util": { "packages": { "@ethereumjs/tx>@ethereumjs/util": true, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography": true, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethjs-util": true, + "@ethereumjs/tx>ethereum-cryptography": true, "bn.js": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "eth-sig-util>tweetnacl": true, "eth-sig-util>tweetnacl-util": true } }, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography": { - "globals": { - "TextDecoder": true, - "crypto": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography>@noble/hashes": true - } - }, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography>@noble/hashes": { - "globals": { - "TextEncoder": true, - "crypto": true - } - }, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethjs-util": { - "packages": { - "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true - } - }, "@metamask/eth-snap-keyring>@metamask/keyring-api": { "packages": { "@metamask/eth-snap-keyring>@metamask/keyring-api>@metamask/utils": true, @@ -1370,11 +1340,11 @@ "@metamask/eth-token-tracker>ethjs>ethjs-abi": true, "@metamask/eth-token-tracker>ethjs>ethjs-contract": true, "@metamask/eth-token-tracker>ethjs>ethjs-query": true, + "@metamask/eth-token-tracker>ethjs>ethjs-util": true, "browserify>buffer": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-provider-http": true, "ethjs>ethjs-unit": true, - "ethjs>ethjs-util": true, "ethjs>js-sha3": true, "ethjs>number-to-bn": true } @@ -1390,9 +1360,9 @@ "@metamask/eth-token-tracker>ethjs>ethjs-contract": { "packages": { "@metamask/eth-token-tracker>ethjs>ethjs-contract>ethjs-abi": true, + "@metamask/eth-token-tracker>ethjs>ethjs-util": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, - "ethjs>ethjs-util": true, "ethjs>js-sha3": true, "promise-to-callback": true } @@ -1416,6 +1386,13 @@ "promise-to-callback": true } }, + "@metamask/eth-token-tracker>ethjs>ethjs-util": { + "packages": { + "browserify>buffer": true, + "ethjs>ethjs-util>is-hex-prefixed": true, + "ethjs>ethjs-util>strip-hex-prefix": true + } + }, "@metamask/eth-token-tracker>safe-event-emitter": { "globals": { "setTimeout": true @@ -1716,14 +1693,25 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, + "@metamask/message-manager>@metamask/eth-sig-util": true, "@metamask/message-manager>jsonschema": true, "browserify>buffer": true, "browserify>events": true, - "eth-sig-util": true, "ethereumjs-util": true, "uuid": true } }, + "@metamask/message-manager>@metamask/eth-sig-util": { + "packages": { + "@ethereumjs/tx>@ethereumjs/util": true, + "@ethereumjs/tx>ethereum-cryptography": true, + "bn.js": true, + "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, + "eth-sig-util>tweetnacl": true, + "eth-sig-util>tweetnacl-util": true + } + }, "@metamask/message-manager>jsonschema": { "packages": { "browserify>url": true @@ -3977,14 +3965,22 @@ "bn.js": true, "browserify>assert": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethereum-cryptography": true, "eth-sig-util>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, "ethereumjs-wallet>safe-buffer": true, "ganache>secp256k1>elliptic": true } }, + "eth-sig-util>ethereumjs-util>ethereum-cryptography": { + "packages": { + "browserify>buffer": true, + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true + } + }, "eth-sig-util>ethereumjs-util>ethjs-util": { "packages": { "browserify>buffer": true, @@ -4023,18 +4019,19 @@ "bn.js": true, "browserify>assert": true, "browserify>buffer": true, - "ethereumjs-abi>ethereumjs-util>ethjs-util": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, + "ethereumjs-abi>ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, "ganache>secp256k1>elliptic": true } }, - "ethereumjs-abi>ethereumjs-util>ethjs-util": { + "ethereumjs-abi>ethereumjs-util>ethereum-cryptography": { "packages": { "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true } }, "ethereumjs-util": { @@ -4214,25 +4211,26 @@ "ethereumjs-wallet>safe-buffer": true } }, + "ethereumjs-wallet>ethereum-cryptography": { + "packages": { + "browserify>buffer": true, + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true + } + }, "ethereumjs-wallet>ethereumjs-util": { "packages": { "bn.js": true, "browserify>assert": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>ethereumjs-util>ethjs-util": true, + "ethereumjs-wallet>ethereum-cryptography": true, "ganache>secp256k1>elliptic": true } }, - "ethereumjs-wallet>ethereumjs-util>ethjs-util": { - "packages": { - "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true - } - }, "ethereumjs-wallet>randombytes": { "globals": { "crypto": true, @@ -4287,9 +4285,9 @@ "ethjs-contract": { "packages": { "ethjs-contract>ethjs-abi": true, + "ethjs-contract>ethjs-util": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, - "ethjs>ethjs-util": true, "ethjs>js-sha3": true, "promise-to-callback": true } @@ -4302,6 +4300,13 @@ "ethjs>number-to-bn": true } }, + "ethjs-contract>ethjs-util": { + "packages": { + "browserify>buffer": true, + "ethjs>ethjs-util>is-hex-prefixed": true, + "ethjs>ethjs-util>strip-hex-prefix": true + } + }, "ethjs-query": { "globals": { "console": true @@ -4332,11 +4337,18 @@ "ethjs-query>ethjs-format": { "packages": { "ethjs-query>ethjs-format>ethjs-schema": true, - "ethjs>ethjs-util": true, + "ethjs-query>ethjs-format>ethjs-util": true, "ethjs>ethjs-util>strip-hex-prefix": true, "ethjs>number-to-bn": true } }, + "ethjs-query>ethjs-format>ethjs-util": { + "packages": { + "browserify>buffer": true, + "ethjs>ethjs-util>is-hex-prefixed": true, + "ethjs>ethjs-util>strip-hex-prefix": true + } + }, "ethjs-query>ethjs-rpc": { "packages": { "promise-to-callback": true diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index 682b9ad41f31..4f181ab36329 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -173,29 +173,13 @@ "packages": { "@ethereumjs/tx>@chainsafe/ssz": true, "@ethereumjs/tx>@ethereumjs/rlp": true, - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography": true, "@ethereumjs/tx>@ethereumjs/util>micro-ftch": true, + "@ethereumjs/tx>ethereum-cryptography": true, "browserify>buffer": true, "browserify>events": true, "browserify>insert-module-globals>is-buffer": true } }, - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography": { - "globals": { - "TextDecoder": true, - "crypto": true - }, - "packages": { - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography>@noble/hashes": true, - "@ethereumjs/tx>ethereum-cryptography>@noble/curves": true - } - }, - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography>@noble/hashes": { - "globals": { - "TextEncoder": true, - "crypto": true - } - }, "@ethereumjs/tx>@ethereumjs/util>micro-ftch": { "globals": { "Headers": true, @@ -220,6 +204,7 @@ "crypto": true }, "packages": { + "@ethereumjs/tx>ethereum-cryptography>@noble/curves": true, "@ethereumjs/tx>ethereum-cryptography>@noble/hashes": true } }, @@ -887,8 +872,8 @@ "setTimeout": true }, "packages": { + "@metamask/controller-utils>@metamask/utils": true, "@metamask/controller-utils>@spruceid/siwe-parser": true, - "@metamask/utils": true, "browserify>buffer": true, "eslint>fast-deep-equal": true, "eth-ens-namehash": true, @@ -896,6 +881,19 @@ "ethjs>ethjs-unit": true } }, + "@metamask/controller-utils>@metamask/utils": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "@metamask/key-tree>@noble/hashes": true, + "browserify>buffer": true, + "nock>debug": true, + "semver": true, + "superstruct": true + } + }, "@metamask/controller-utils>@spruceid/siwe-parser": { "globals": { "console.error": true, @@ -1096,9 +1094,9 @@ "packages": { "@ethereumjs/tx>@ethereumjs/util": true, "@metamask/eth-keyring-controller>@metamask/eth-sig-util>ethereum-cryptography": true, - "@metamask/eth-keyring-controller>@metamask/eth-sig-util>ethjs-util": true, "bn.js": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "eth-sig-util>tweetnacl": true, "eth-sig-util>tweetnacl-util": true } @@ -1118,13 +1116,6 @@ "crypto": true } }, - "@metamask/eth-keyring-controller>@metamask/eth-sig-util>ethjs-util": { - "packages": { - "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true - } - }, "@metamask/eth-keyring-controller>@metamask/eth-simple-keyring": { "packages": { "@ethereumjs/tx>@ethereumjs/util": true, @@ -1185,22 +1176,23 @@ }, "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util": { "packages": { - "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethjs-util": true, + "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethereum-cryptography": true, "bn.js": true, "browserify>assert": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, "ethereumjs-wallet>safe-buffer": true, "ganache>secp256k1>elliptic": true } }, - "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethjs-util": { + "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethereum-cryptography": { "packages": { "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true } }, "@metamask/eth-ledger-bridge-keyring>hdkey": { @@ -1239,36 +1231,14 @@ "@metamask/eth-snap-keyring>@metamask/eth-sig-util": { "packages": { "@ethereumjs/tx>@ethereumjs/util": true, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography": true, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethjs-util": true, + "@ethereumjs/tx>ethereum-cryptography": true, "bn.js": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "eth-sig-util>tweetnacl": true, "eth-sig-util>tweetnacl-util": true } }, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography": { - "globals": { - "TextDecoder": true, - "crypto": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography>@noble/hashes": true - } - }, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography>@noble/hashes": { - "globals": { - "TextEncoder": true, - "crypto": true - } - }, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethjs-util": { - "packages": { - "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true - } - }, "@metamask/eth-snap-keyring>@metamask/keyring-api": { "packages": { "@metamask/eth-snap-keyring>@metamask/keyring-api>@metamask/utils": true, @@ -1370,11 +1340,11 @@ "@metamask/eth-token-tracker>ethjs>ethjs-abi": true, "@metamask/eth-token-tracker>ethjs>ethjs-contract": true, "@metamask/eth-token-tracker>ethjs>ethjs-query": true, + "@metamask/eth-token-tracker>ethjs>ethjs-util": true, "browserify>buffer": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-provider-http": true, "ethjs>ethjs-unit": true, - "ethjs>ethjs-util": true, "ethjs>js-sha3": true, "ethjs>number-to-bn": true } @@ -1390,9 +1360,9 @@ "@metamask/eth-token-tracker>ethjs>ethjs-contract": { "packages": { "@metamask/eth-token-tracker>ethjs>ethjs-contract>ethjs-abi": true, + "@metamask/eth-token-tracker>ethjs>ethjs-util": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, - "ethjs>ethjs-util": true, "ethjs>js-sha3": true, "promise-to-callback": true } @@ -1416,6 +1386,13 @@ "promise-to-callback": true } }, + "@metamask/eth-token-tracker>ethjs>ethjs-util": { + "packages": { + "browserify>buffer": true, + "ethjs>ethjs-util>is-hex-prefixed": true, + "ethjs>ethjs-util>strip-hex-prefix": true + } + }, "@metamask/eth-token-tracker>safe-event-emitter": { "globals": { "setTimeout": true @@ -1716,14 +1693,25 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, + "@metamask/message-manager>@metamask/eth-sig-util": true, "@metamask/message-manager>jsonschema": true, "browserify>buffer": true, "browserify>events": true, - "eth-sig-util": true, "ethereumjs-util": true, "uuid": true } }, + "@metamask/message-manager>@metamask/eth-sig-util": { + "packages": { + "@ethereumjs/tx>@ethereumjs/util": true, + "@ethereumjs/tx>ethereum-cryptography": true, + "bn.js": true, + "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, + "eth-sig-util>tweetnacl": true, + "eth-sig-util>tweetnacl-util": true + } + }, "@metamask/message-manager>jsonschema": { "packages": { "browserify>url": true @@ -3977,14 +3965,22 @@ "bn.js": true, "browserify>assert": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethereum-cryptography": true, "eth-sig-util>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, "ethereumjs-wallet>safe-buffer": true, "ganache>secp256k1>elliptic": true } }, + "eth-sig-util>ethereumjs-util>ethereum-cryptography": { + "packages": { + "browserify>buffer": true, + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true + } + }, "eth-sig-util>ethereumjs-util>ethjs-util": { "packages": { "browserify>buffer": true, @@ -4023,18 +4019,19 @@ "bn.js": true, "browserify>assert": true, "browserify>buffer": true, - "ethereumjs-abi>ethereumjs-util>ethjs-util": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, + "ethereumjs-abi>ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, "ganache>secp256k1>elliptic": true } }, - "ethereumjs-abi>ethereumjs-util>ethjs-util": { + "ethereumjs-abi>ethereumjs-util>ethereum-cryptography": { "packages": { "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true } }, "ethereumjs-util": { @@ -4214,25 +4211,26 @@ "ethereumjs-wallet>safe-buffer": true } }, + "ethereumjs-wallet>ethereum-cryptography": { + "packages": { + "browserify>buffer": true, + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true + } + }, "ethereumjs-wallet>ethereumjs-util": { "packages": { "bn.js": true, "browserify>assert": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>ethereumjs-util>ethjs-util": true, + "ethereumjs-wallet>ethereum-cryptography": true, "ganache>secp256k1>elliptic": true } }, - "ethereumjs-wallet>ethereumjs-util>ethjs-util": { - "packages": { - "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true - } - }, "ethereumjs-wallet>randombytes": { "globals": { "crypto": true, @@ -4287,9 +4285,9 @@ "ethjs-contract": { "packages": { "ethjs-contract>ethjs-abi": true, + "ethjs-contract>ethjs-util": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, - "ethjs>ethjs-util": true, "ethjs>js-sha3": true, "promise-to-callback": true } @@ -4302,6 +4300,13 @@ "ethjs>number-to-bn": true } }, + "ethjs-contract>ethjs-util": { + "packages": { + "browserify>buffer": true, + "ethjs>ethjs-util>is-hex-prefixed": true, + "ethjs>ethjs-util>strip-hex-prefix": true + } + }, "ethjs-query": { "globals": { "console": true @@ -4332,11 +4337,18 @@ "ethjs-query>ethjs-format": { "packages": { "ethjs-query>ethjs-format>ethjs-schema": true, - "ethjs>ethjs-util": true, + "ethjs-query>ethjs-format>ethjs-util": true, "ethjs>ethjs-util>strip-hex-prefix": true, "ethjs>number-to-bn": true } }, + "ethjs-query>ethjs-format>ethjs-util": { + "packages": { + "browserify>buffer": true, + "ethjs>ethjs-util>is-hex-prefixed": true, + "ethjs>ethjs-util>strip-hex-prefix": true + } + }, "ethjs-query>ethjs-rpc": { "packages": { "promise-to-callback": true diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index 3afc49c783b8..0ac70c31e4a4 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -173,29 +173,13 @@ "packages": { "@ethereumjs/tx>@chainsafe/ssz": true, "@ethereumjs/tx>@ethereumjs/rlp": true, - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography": true, "@ethereumjs/tx>@ethereumjs/util>micro-ftch": true, + "@ethereumjs/tx>ethereum-cryptography": true, "browserify>buffer": true, "browserify>events": true, "browserify>insert-module-globals>is-buffer": true } }, - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography": { - "globals": { - "TextDecoder": true, - "crypto": true - }, - "packages": { - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography>@noble/hashes": true, - "@ethereumjs/tx>ethereum-cryptography>@noble/curves": true - } - }, - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography>@noble/hashes": { - "globals": { - "TextEncoder": true, - "crypto": true - } - }, "@ethereumjs/tx>@ethereumjs/util>micro-ftch": { "globals": { "Headers": true, @@ -220,6 +204,7 @@ "crypto": true }, "packages": { + "@ethereumjs/tx>ethereum-cryptography>@noble/curves": true, "@ethereumjs/tx>ethereum-cryptography>@noble/hashes": true } }, @@ -887,8 +872,8 @@ "setTimeout": true }, "packages": { + "@metamask/controller-utils>@metamask/utils": true, "@metamask/controller-utils>@spruceid/siwe-parser": true, - "@metamask/utils": true, "browserify>buffer": true, "eslint>fast-deep-equal": true, "eth-ens-namehash": true, @@ -896,6 +881,19 @@ "ethjs>ethjs-unit": true } }, + "@metamask/controller-utils>@metamask/utils": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "@metamask/key-tree>@noble/hashes": true, + "browserify>buffer": true, + "nock>debug": true, + "semver": true, + "superstruct": true + } + }, "@metamask/controller-utils>@spruceid/siwe-parser": { "globals": { "console.error": true, @@ -1025,9 +1023,9 @@ "packages": { "@ethereumjs/tx>@ethereumjs/util": true, "@metamask/eth-keyring-controller>@metamask/eth-sig-util>ethereum-cryptography": true, - "@metamask/eth-keyring-controller>@metamask/eth-sig-util>ethjs-util": true, "bn.js": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "eth-sig-util>tweetnacl": true, "eth-sig-util>tweetnacl-util": true } @@ -1047,13 +1045,6 @@ "crypto": true } }, - "@metamask/eth-keyring-controller>@metamask/eth-sig-util>ethjs-util": { - "packages": { - "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true - } - }, "@metamask/eth-keyring-controller>@metamask/eth-simple-keyring": { "packages": { "@ethereumjs/tx>@ethereumjs/util": true, @@ -1114,22 +1105,23 @@ }, "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util": { "packages": { - "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethjs-util": true, + "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethereum-cryptography": true, "bn.js": true, "browserify>assert": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, "ethereumjs-wallet>safe-buffer": true, "ganache>secp256k1>elliptic": true } }, - "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethjs-util": { + "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethereum-cryptography": { "packages": { "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true } }, "@metamask/eth-ledger-bridge-keyring>hdkey": { @@ -1154,36 +1146,14 @@ "@metamask/eth-snap-keyring>@metamask/eth-sig-util": { "packages": { "@ethereumjs/tx>@ethereumjs/util": true, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography": true, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethjs-util": true, + "@ethereumjs/tx>ethereum-cryptography": true, "bn.js": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "eth-sig-util>tweetnacl": true, "eth-sig-util>tweetnacl-util": true } }, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography": { - "globals": { - "TextDecoder": true, - "crypto": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography>@noble/hashes": true - } - }, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography>@noble/hashes": { - "globals": { - "TextEncoder": true, - "crypto": true - } - }, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethjs-util": { - "packages": { - "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true - } - }, "@metamask/eth-token-tracker": { "globals": { "console.warn": true @@ -1242,11 +1212,11 @@ "@metamask/eth-token-tracker>ethjs>ethjs-abi": true, "@metamask/eth-token-tracker>ethjs>ethjs-contract": true, "@metamask/eth-token-tracker>ethjs>ethjs-query": true, + "@metamask/eth-token-tracker>ethjs>ethjs-util": true, "browserify>buffer": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-provider-http": true, "ethjs>ethjs-unit": true, - "ethjs>ethjs-util": true, "ethjs>js-sha3": true, "ethjs>number-to-bn": true } @@ -1262,9 +1232,9 @@ "@metamask/eth-token-tracker>ethjs>ethjs-contract": { "packages": { "@metamask/eth-token-tracker>ethjs>ethjs-contract>ethjs-abi": true, + "@metamask/eth-token-tracker>ethjs>ethjs-util": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, - "ethjs>ethjs-util": true, "ethjs>js-sha3": true, "promise-to-callback": true } @@ -1288,6 +1258,13 @@ "promise-to-callback": true } }, + "@metamask/eth-token-tracker>ethjs>ethjs-util": { + "packages": { + "browserify>buffer": true, + "ethjs>ethjs-util>is-hex-prefixed": true, + "ethjs>ethjs-util>strip-hex-prefix": true + } + }, "@metamask/eth-token-tracker>safe-event-emitter": { "globals": { "setTimeout": true @@ -1565,14 +1542,25 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, + "@metamask/message-manager>@metamask/eth-sig-util": true, "@metamask/message-manager>jsonschema": true, "browserify>buffer": true, "browserify>events": true, - "eth-sig-util": true, "ethereumjs-util": true, "uuid": true } }, + "@metamask/message-manager>@metamask/eth-sig-util": { + "packages": { + "@ethereumjs/tx>@ethereumjs/util": true, + "@ethereumjs/tx>ethereum-cryptography": true, + "bn.js": true, + "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, + "eth-sig-util>tweetnacl": true, + "eth-sig-util>tweetnacl-util": true + } + }, "@metamask/message-manager>jsonschema": { "packages": { "browserify>url": true @@ -3481,14 +3469,22 @@ "bn.js": true, "browserify>assert": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethereum-cryptography": true, "eth-sig-util>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, "ethereumjs-wallet>safe-buffer": true, "ganache>secp256k1>elliptic": true } }, + "eth-sig-util>ethereumjs-util>ethereum-cryptography": { + "packages": { + "browserify>buffer": true, + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true + } + }, "eth-sig-util>ethereumjs-util>ethjs-util": { "packages": { "browserify>buffer": true, @@ -3527,18 +3523,19 @@ "bn.js": true, "browserify>assert": true, "browserify>buffer": true, - "ethereumjs-abi>ethereumjs-util>ethjs-util": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, + "ethereumjs-abi>ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, "ganache>secp256k1>elliptic": true } }, - "ethereumjs-abi>ethereumjs-util>ethjs-util": { + "ethereumjs-abi>ethereumjs-util>ethereum-cryptography": { "packages": { "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true } }, "ethereumjs-util": { @@ -3718,25 +3715,26 @@ "ethereumjs-wallet>safe-buffer": true } }, + "ethereumjs-wallet>ethereum-cryptography": { + "packages": { + "browserify>buffer": true, + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true + } + }, "ethereumjs-wallet>ethereumjs-util": { "packages": { "bn.js": true, "browserify>assert": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>ethereumjs-util>ethjs-util": true, + "ethereumjs-wallet>ethereum-cryptography": true, "ganache>secp256k1>elliptic": true } }, - "ethereumjs-wallet>ethereumjs-util>ethjs-util": { - "packages": { - "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true - } - }, "ethereumjs-wallet>randombytes": { "globals": { "crypto": true, @@ -3791,9 +3789,9 @@ "ethjs-contract": { "packages": { "ethjs-contract>ethjs-abi": true, + "ethjs-contract>ethjs-util": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, - "ethjs>ethjs-util": true, "ethjs>js-sha3": true, "promise-to-callback": true } @@ -3806,6 +3804,13 @@ "ethjs>number-to-bn": true } }, + "ethjs-contract>ethjs-util": { + "packages": { + "browserify>buffer": true, + "ethjs>ethjs-util>is-hex-prefixed": true, + "ethjs>ethjs-util>strip-hex-prefix": true + } + }, "ethjs-query": { "globals": { "console": true @@ -3836,11 +3841,18 @@ "ethjs-query>ethjs-format": { "packages": { "ethjs-query>ethjs-format>ethjs-schema": true, - "ethjs>ethjs-util": true, + "ethjs-query>ethjs-format>ethjs-util": true, "ethjs>ethjs-util>strip-hex-prefix": true, "ethjs>number-to-bn": true } }, + "ethjs-query>ethjs-format>ethjs-util": { + "packages": { + "browserify>buffer": true, + "ethjs>ethjs-util>is-hex-prefixed": true, + "ethjs>ethjs-util>strip-hex-prefix": true + } + }, "ethjs-query>ethjs-rpc": { "packages": { "promise-to-callback": true diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json index 4d19d9c67fad..5d216d8831f5 100644 --- a/lavamoat/browserify/mmi/policy.json +++ b/lavamoat/browserify/mmi/policy.json @@ -173,29 +173,13 @@ "packages": { "@ethereumjs/tx>@chainsafe/ssz": true, "@ethereumjs/tx>@ethereumjs/rlp": true, - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography": true, "@ethereumjs/tx>@ethereumjs/util>micro-ftch": true, + "@ethereumjs/tx>ethereum-cryptography": true, "browserify>buffer": true, "browserify>events": true, "browserify>insert-module-globals>is-buffer": true } }, - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography": { - "globals": { - "TextDecoder": true, - "crypto": true - }, - "packages": { - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography>@noble/hashes": true, - "@ethereumjs/tx>ethereum-cryptography>@noble/curves": true - } - }, - "@ethereumjs/tx>@ethereumjs/util>ethereum-cryptography>@noble/hashes": { - "globals": { - "TextEncoder": true, - "crypto": true - } - }, "@ethereumjs/tx>@ethereumjs/util>micro-ftch": { "globals": { "Headers": true, @@ -220,6 +204,7 @@ "crypto": true }, "packages": { + "@ethereumjs/tx>ethereum-cryptography>@noble/curves": true, "@ethereumjs/tx>ethereum-cryptography>@noble/hashes": true } }, @@ -1115,8 +1100,8 @@ "setTimeout": true }, "packages": { + "@metamask/controller-utils>@metamask/utils": true, "@metamask/controller-utils>@spruceid/siwe-parser": true, - "@metamask/utils": true, "browserify>buffer": true, "eslint>fast-deep-equal": true, "eth-ens-namehash": true, @@ -1124,6 +1109,19 @@ "ethjs>ethjs-unit": true } }, + "@metamask/controller-utils>@metamask/utils": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "@metamask/key-tree>@noble/hashes": true, + "browserify>buffer": true, + "nock>debug": true, + "semver": true, + "superstruct": true + } + }, "@metamask/controller-utils>@spruceid/siwe-parser": { "globals": { "console.error": true, @@ -1253,9 +1251,9 @@ "packages": { "@ethereumjs/tx>@ethereumjs/util": true, "@metamask/eth-keyring-controller>@metamask/eth-sig-util>ethereum-cryptography": true, - "@metamask/eth-keyring-controller>@metamask/eth-sig-util>ethjs-util": true, "bn.js": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "eth-sig-util>tweetnacl": true, "eth-sig-util>tweetnacl-util": true } @@ -1275,13 +1273,6 @@ "crypto": true } }, - "@metamask/eth-keyring-controller>@metamask/eth-sig-util>ethjs-util": { - "packages": { - "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true - } - }, "@metamask/eth-keyring-controller>@metamask/eth-simple-keyring": { "packages": { "@ethereumjs/tx>@ethereumjs/util": true, @@ -1342,22 +1333,23 @@ }, "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util": { "packages": { - "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethjs-util": true, + "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethereum-cryptography": true, "bn.js": true, "browserify>assert": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, "ethereumjs-wallet>safe-buffer": true, "ganache>secp256k1>elliptic": true } }, - "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethjs-util": { + "@metamask/eth-ledger-bridge-keyring>eth-sig-util>ethereumjs-util>ethereum-cryptography": { "packages": { "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true } }, "@metamask/eth-ledger-bridge-keyring>hdkey": { @@ -1382,36 +1374,14 @@ "@metamask/eth-snap-keyring>@metamask/eth-sig-util": { "packages": { "@ethereumjs/tx>@ethereumjs/util": true, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography": true, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethjs-util": true, + "@ethereumjs/tx>ethereum-cryptography": true, "bn.js": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "eth-sig-util>tweetnacl": true, "eth-sig-util>tweetnacl-util": true } }, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography": { - "globals": { - "TextDecoder": true, - "crypto": true - }, - "packages": { - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography>@noble/hashes": true - } - }, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethereum-cryptography>@noble/hashes": { - "globals": { - "TextEncoder": true, - "crypto": true - } - }, - "@metamask/eth-snap-keyring>@metamask/eth-sig-util>ethjs-util": { - "packages": { - "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true - } - }, "@metamask/eth-token-tracker": { "globals": { "console.warn": true @@ -1470,11 +1440,11 @@ "@metamask/eth-token-tracker>ethjs>ethjs-abi": true, "@metamask/eth-token-tracker>ethjs>ethjs-contract": true, "@metamask/eth-token-tracker>ethjs>ethjs-query": true, + "@metamask/eth-token-tracker>ethjs>ethjs-util": true, "browserify>buffer": true, "ethjs>ethjs-filter": true, "ethjs>ethjs-provider-http": true, "ethjs>ethjs-unit": true, - "ethjs>ethjs-util": true, "ethjs>js-sha3": true, "ethjs>number-to-bn": true } @@ -1490,9 +1460,9 @@ "@metamask/eth-token-tracker>ethjs>ethjs-contract": { "packages": { "@metamask/eth-token-tracker>ethjs>ethjs-contract>ethjs-abi": true, + "@metamask/eth-token-tracker>ethjs>ethjs-util": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, - "ethjs>ethjs-util": true, "ethjs>js-sha3": true, "promise-to-callback": true } @@ -1516,6 +1486,13 @@ "promise-to-callback": true } }, + "@metamask/eth-token-tracker>ethjs>ethjs-util": { + "packages": { + "browserify>buffer": true, + "ethjs>ethjs-util>is-hex-prefixed": true, + "ethjs>ethjs-util>strip-hex-prefix": true + } + }, "@metamask/eth-token-tracker>safe-event-emitter": { "globals": { "setTimeout": true @@ -1793,14 +1770,25 @@ "packages": { "@metamask/base-controller": true, "@metamask/controller-utils": true, + "@metamask/message-manager>@metamask/eth-sig-util": true, "@metamask/message-manager>jsonschema": true, "browserify>buffer": true, "browserify>events": true, - "eth-sig-util": true, "ethereumjs-util": true, "uuid": true } }, + "@metamask/message-manager>@metamask/eth-sig-util": { + "packages": { + "@ethereumjs/tx>@ethereumjs/util": true, + "@ethereumjs/tx>ethereum-cryptography": true, + "bn.js": true, + "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, + "eth-sig-util>tweetnacl": true, + "eth-sig-util>tweetnacl-util": true + } + }, "@metamask/message-manager>jsonschema": { "packages": { "browserify>url": true @@ -3709,14 +3697,22 @@ "bn.js": true, "browserify>assert": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethereum-cryptography": true, "eth-sig-util>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, "ethereumjs-wallet>safe-buffer": true, "ganache>secp256k1>elliptic": true } }, + "eth-sig-util>ethereumjs-util>ethereum-cryptography": { + "packages": { + "browserify>buffer": true, + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true + } + }, "eth-sig-util>ethereumjs-util>ethjs-util": { "packages": { "browserify>buffer": true, @@ -3755,18 +3751,19 @@ "bn.js": true, "browserify>assert": true, "browserify>buffer": true, - "ethereumjs-abi>ethereumjs-util>ethjs-util": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, + "ethereumjs-abi>ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, "ganache>secp256k1>elliptic": true } }, - "ethereumjs-abi>ethereumjs-util>ethjs-util": { + "ethereumjs-abi>ethereumjs-util>ethereum-cryptography": { "packages": { "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true } }, "ethereumjs-util": { @@ -3946,25 +3943,26 @@ "ethereumjs-wallet>safe-buffer": true } }, + "ethereumjs-wallet>ethereum-cryptography": { + "packages": { + "browserify>buffer": true, + "ethereumjs-util>ethereum-cryptography>keccak": true, + "ethereumjs-util>ethereum-cryptography>secp256k1": true, + "ethereumjs-wallet>randombytes": true + } + }, "ethereumjs-wallet>ethereumjs-util": { "packages": { "bn.js": true, "browserify>assert": true, "browserify>buffer": true, + "eth-sig-util>ethereumjs-util>ethjs-util": true, "ethereumjs-util>create-hash": true, - "ethereumjs-util>ethereum-cryptography": true, "ethereumjs-util>rlp": true, - "ethereumjs-wallet>ethereumjs-util>ethjs-util": true, + "ethereumjs-wallet>ethereum-cryptography": true, "ganache>secp256k1>elliptic": true } }, - "ethereumjs-wallet>ethereumjs-util>ethjs-util": { - "packages": { - "browserify>buffer": true, - "ethjs>ethjs-util>is-hex-prefixed": true, - "ethjs>ethjs-util>strip-hex-prefix": true - } - }, "ethereumjs-wallet>randombytes": { "globals": { "crypto": true, @@ -4019,9 +4017,9 @@ "ethjs-contract": { "packages": { "ethjs-contract>ethjs-abi": true, + "ethjs-contract>ethjs-util": true, "ethjs-query>babel-runtime": true, "ethjs>ethjs-filter": true, - "ethjs>ethjs-util": true, "ethjs>js-sha3": true, "promise-to-callback": true } @@ -4034,6 +4032,13 @@ "ethjs>number-to-bn": true } }, + "ethjs-contract>ethjs-util": { + "packages": { + "browserify>buffer": true, + "ethjs>ethjs-util>is-hex-prefixed": true, + "ethjs>ethjs-util>strip-hex-prefix": true + } + }, "ethjs-query": { "globals": { "console": true @@ -4064,11 +4069,18 @@ "ethjs-query>ethjs-format": { "packages": { "ethjs-query>ethjs-format>ethjs-schema": true, - "ethjs>ethjs-util": true, + "ethjs-query>ethjs-format>ethjs-util": true, "ethjs>ethjs-util>strip-hex-prefix": true, "ethjs>number-to-bn": true } }, + "ethjs-query>ethjs-format>ethjs-util": { + "packages": { + "browserify>buffer": true, + "ethjs>ethjs-util>is-hex-prefixed": true, + "ethjs>ethjs-util>strip-hex-prefix": true + } + }, "ethjs-query>ethjs-rpc": { "packages": { "promise-to-callback": true diff --git a/lavamoat/build-system/policy.json b/lavamoat/build-system/policy.json index 13d870eab3e6..c06248a42fb5 100644 --- a/lavamoat/build-system/policy.json +++ b/lavamoat/build-system/policy.json @@ -1129,13 +1129,6 @@ "@metamask/jazzicon>color>color-convert>color-name": true } }, - "@sentry/cli>mkdirp": { - "builtin": { - "fs": true, - "path.dirname": true, - "path.resolve": true - } - }, "@storybook/addon-knobs>qs": { "packages": { "string.prototype.matchall>side-channel": true @@ -8158,7 +8151,14 @@ "path.dirname": true }, "packages": { - "@sentry/cli>mkdirp": true + "stylelint>file-entry-cache>flat-cache>write>mkdirp": true + } + }, + "stylelint>file-entry-cache>flat-cache>write>mkdirp": { + "builtin": { + "fs": true, + "path.dirname": true, + "path.resolve": true } }, "stylelint>global-modules": { diff --git a/package.json b/package.json index f2f9c2b93e91..4e969a192d67 100644 --- a/package.json +++ b/package.json @@ -197,8 +197,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", - "lavamoat-core@^14.2.0": "patch:lavamoat-core@npm%3A14.2.0#./.yarn/patches/lavamoat-core-npm-14.2.0-c453f4f755.patch" + "lavamoat-core@^14.2.0": "patch:lavamoat-core@npm%3A14.2.0#./.yarn/patches/lavamoat-core-npm-14.2.0-c453f4f755.patch", + "@metamask/signature-controller@^5.3.0": "patch:@metamask/signature-controller@npm%3A5.3.0#./.yarn/patches/@metamask-signature-controller-npm-5.3.0-225628460b.patch" }, "dependencies": { "@babel/runtime": "^7.18.9", @@ -220,7 +220,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.6", + "@metamask-institutional/extension": "^0.2.1", "@metamask-institutional/institutional-features": "^1.1.8", "@metamask-institutional/portfolio-dashboard": "^1.1.3", "@metamask-institutional/rpc-allowlist": "^1.0.0", @@ -262,7 +262,7 @@ "@metamask/rpc-methods-flask": "npm:@metamask/rpc-methods@0.37.1-flask.1", "@metamask/safe-event-emitter": "^2.0.0", "@metamask/scure-bip39": "^2.0.3", - "@metamask/signature-controller": "^4.0.1", + "@metamask/signature-controller": "^5.3.0", "@metamask/slip44": "^3.0.0", "@metamask/smart-transactions-controller": "^4.0.0", "@metamask/snaps-controllers": "^1.0.0-prerelease.1", @@ -386,7 +386,7 @@ "@metamask/forwarder": "^1.1.0", "@metamask/phishing-warning": "^2.1.0", "@metamask/test-dapp": "^7.0.1", - "@sentry/cli": "^1.58.0", + "@sentry/cli": "^2.19.4", "@storybook/addon-a11y": "^7.0.11", "@storybook/addon-actions": "^7.0.11", "@storybook/addon-essentials": "^7.0.11", diff --git a/shared/constants/security-provider.ts b/shared/constants/security-provider.ts index 1862e81816d4..b956a8e7529b 100644 --- a/shared/constants/security-provider.ts +++ b/shared/constants/security-provider.ts @@ -1,3 +1,60 @@ +export enum SecurityProvider { + Blockaid = 'blockaid', +} + +type SecurityProviderConfig = Record< + SecurityProvider, + { + /** translation key for security provider name */ + readonly tKeyName: string; + /** URL to securty provider website */ + readonly url: string; + } +>; + +export const SECURITY_PROVIDER_CONFIG: Readonly = { + [SecurityProvider.Blockaid]: { + tKeyName: 'blockaid', + url: 'https://blockaid.io/', + }, +}; + +/** The reason, also referred to as the attack type, provided in the PPOM Response */ +export enum BlockaidReason { + /** Approval for a malicious spender */ + approvalFarming = 'approval_farming', + /** Malicious signature on Blur order */ + blurFarming = 'blur_farming', + /** A known malicous site invoked that transaction */ + maliciousDomain = 'malicious_domain', + /** Malicious signature on a Permit order */ + permitFarming = 'permit_farming', + /** Direct theft of native assets (ETH/MATIC/AVAX/ etc …) */ + rawNativeTokenTransfer = 'raw_native_token_transfer', + /** Malicious raw signature from the user */ + rawSignatureFarming = 'raw_signature_farming', + /** Malicious signature on a Seaport order */ + seaportFarming = 'seaport_farming', + /** setApprovalForAll for a malicious operator */ + setApprovalForAll = 'set_approval_for_all', + /** Malicious signature on other type of trade order (Zero-X / Rarible / etc..) */ + tradeOrderFarming = 'trade_order_farming', + /** Direct theft of assets using transfer */ + transferFarming = 'transfer_farming', + /** Direct theft of assets using transferFrom */ + transferFromFarming = 'transfer_from_farming', + /** Malicious trade that results in the victim being rained */ + unfairTrade = 'unfair_trade', + + other = 'other', +} + +export enum BlockaidResultType { + Malicious = 'Malicious', + Warning = 'Warning', + Benign = 'Benign', +} + /** * @typedef {object} SecurityProviderMessageSeverity * @property {0} NOT_MALICIOUS - Indicates message is not malicious diff --git a/test/e2e/snaps/enums.js b/test/e2e/snaps/enums.js index d19c7496766f..acf8f329881c 100644 --- a/test/e2e/snaps/enums.js +++ b/test/e2e/snaps/enums.js @@ -1,5 +1,6 @@ module.exports = { - TEST_SNAPS_WEBSITE_URL: 'https://metamask.github.io/test-snaps/5.5.0/', + TEST_SNAPS_WEBSITE_URL: + 'https://metamask.github.io/snaps/test-snaps/0.37.3-flask.1/', TEST_SNAPS_SIMPLE_KEYRING_WEBSITE_URL: 'https://metamask.github.io/snap-simple-keyring/latest/', }; diff --git a/test/e2e/snaps/test-snap-bip-32.spec.js b/test/e2e/snaps/test-snap-bip-32.spec.js index 0cd744f2cc87..5b69c576619c 100644 --- a/test/e2e/snaps/test-snap-bip-32.spec.js +++ b/test/e2e/snaps/test-snap-bip-32.spec.js @@ -31,10 +31,10 @@ describe('Test Snap bip-32', function () { await driver.delay(1000); // find and scroll to the bip32 test and connect - const snapButton1 = await driver.findElement('#connectBip32'); + const snapButton1 = await driver.findElement('#connectbip32'); await driver.scrollToElement(snapButton1); await driver.delay(1000); - await driver.clickElement('#connectBip32'); + await driver.clickElement('#connectbip32'); await driver.delay(1000); // switch to metamask extension and click connect @@ -84,7 +84,7 @@ describe('Test Snap bip-32', function () { // wait for npm installation success await driver.waitForSelector({ - css: '#connectBip32', + css: '#connectbip32', text: 'Reconnect to BIP-32 Snap', }); diff --git a/test/e2e/snaps/test-snap-bip-44.spec.js b/test/e2e/snaps/test-snap-bip-44.spec.js index 5df417861719..48b2bbfc26a3 100644 --- a/test/e2e/snaps/test-snap-bip-44.spec.js +++ b/test/e2e/snaps/test-snap-bip-44.spec.js @@ -32,10 +32,10 @@ describe('Test Snap bip-44', function () { await driver.delay(1000); // find and scroll to the bip44 test and connect - const snapButton1 = await driver.findElement('#connectBip44Snap'); + const snapButton1 = await driver.findElement('#connectbip44'); await driver.scrollToElement(snapButton1); await driver.delay(1000); - await driver.clickElement('#connectBip44Snap'); + await driver.clickElement('#connectbip44'); await driver.delay(1000); // switch to metamask extension and click connect and approve @@ -53,6 +53,9 @@ describe('Test Snap bip-44', function () { tag: 'button', }); await driver.waitForSelector({ text: 'Install' }); + + await driver.clickElementSafe('[data-testid="snap-install-scroll"]'); + await driver.clickElement({ text: 'Install', tag: 'button', @@ -61,6 +64,7 @@ describe('Test Snap bip-44', function () { // deal with permissions popover await driver.delay(500); await driver.clickElement('#key-access-bip44-1-0'); + await driver.clickElement('#key-access-bip44-3-1'); await driver.clickElement({ text: 'Confirm', tag: 'button', @@ -76,7 +80,7 @@ describe('Test Snap bip-44', function () { // wait for npm installation success await driver.waitForSelector({ - css: '#connectBip44Snap', + css: '#connectbip44', text: 'Reconnect to BIP-44 Snap', }); diff --git a/test/e2e/snaps/test-snap-cronjob.spec.js b/test/e2e/snaps/test-snap-cronjob.spec.js index 7fb31e361f6a..8495e953d409 100644 --- a/test/e2e/snaps/test-snap-cronjob.spec.js +++ b/test/e2e/snaps/test-snap-cronjob.spec.js @@ -31,10 +31,10 @@ describe('Test Snap Cronjob', function () { // navigate to test snaps page and connect await driver.openNewPage(TEST_SNAPS_WEBSITE_URL); await driver.delay(1000); - const snapButton = await driver.findElement('#connectCronjobSnap'); + const snapButton = await driver.findElement('#connectcronjobs'); await driver.scrollToElement(snapButton); await driver.delay(1000); - await driver.clickElement('#connectCronjobSnap'); + await driver.clickElement('#connectcronjobs'); await driver.delay(1000); // switch to metamask extension and click connect @@ -71,8 +71,8 @@ describe('Test Snap Cronjob', function () { // wait for npm installation success await driver.waitForSelector({ - css: '#connectCronjobSnap', - text: 'Reconnect to Cronjob Snap', + css: '#connectcronjobs', + text: 'Reconnect to Cronjobs Snap', }); // switch to dialog popup, wait for a maximum of 65 seconds @@ -86,7 +86,10 @@ describe('Test Snap Cronjob', function () { // look for the dialog popup to verify cronjob fired const error = await driver.findElement('.snap-delineator__content'); const text = await error.getText(); - assert.equal(text.includes(`Cronjob\nfired`), true); + assert.equal( + text.includes(`Cronjob\nThis dialog was triggered by a cronjob.`), + true, + ); // try to click on the Ok button and pass test if it works await driver.clickElement({ diff --git a/test/e2e/snaps/test-snap-dialog.spec.js b/test/e2e/snaps/test-snap-dialog.spec.js index 28825c0e2f22..e675a9910019 100644 --- a/test/e2e/snaps/test-snap-dialog.spec.js +++ b/test/e2e/snaps/test-snap-dialog.spec.js @@ -31,10 +31,10 @@ describe('Test Snap Dialog', function () { // navigate to test snaps page and connect to dialog snap await driver.openNewPage(TEST_SNAPS_WEBSITE_URL); await driver.delay(1000); - const dialogButton = await driver.findElement('#connectDialogSnap'); + const dialogButton = await driver.findElement('#connectdialogs'); await driver.scrollToElement(dialogButton); await driver.delay(1000); - await driver.clickElement('#connectDialogSnap'); + await driver.clickElement('#connectdialogs'); await driver.delay(1000); // switch to metamask extension and click connect @@ -71,8 +71,8 @@ describe('Test Snap Dialog', function () { // wait for npm installation success await driver.waitForSelector({ - css: '#connectDialogSnap', - text: 'Reconnect to Dialog Snap', + css: '#connectdialogs', + text: 'Reconnect to Dialogs Snap', }); // click on alert dialog @@ -91,7 +91,10 @@ describe('Test Snap Dialog', function () { let result = await driver.findElement('.snap-ui-renderer__panel'); await driver.scrollToElement(result); await driver.delay(500); - assert.equal(await result.getText(), 'Alert Dialog\nText here'); + assert.equal( + await result.getText(), + 'Alert Dialog\nThis is an alert dialog. It has a single button: "OK".', + ); // click ok button await driver.clickElement({ @@ -109,7 +112,7 @@ describe('Test Snap Dialog', function () { assert.equal(await result.getText(), 'null'); // click conf button - await driver.clickElement('#sendConfButton'); + await driver.clickElement('#sendConfirmationButton'); await driver.delay(500); // switch to dialog popup @@ -136,7 +139,7 @@ describe('Test Snap Dialog', function () { assert.equal(await result.getText(), 'false'); // click conf button again - await driver.clickElement('#sendConfButton'); + await driver.clickElement('#sendConfirmationButton'); await driver.delay(500); // switch to dialog popup diff --git a/test/e2e/snaps/test-snap-error.spec.js b/test/e2e/snaps/test-snap-error.spec.js index c8e17efdce0f..9c19cd7234ec 100644 --- a/test/e2e/snaps/test-snap-error.spec.js +++ b/test/e2e/snaps/test-snap-error.spec.js @@ -31,10 +31,10 @@ describe('Test Snap Error', function () { // navigate to test snaps page and connect await driver.openNewPage(TEST_SNAPS_WEBSITE_URL); await driver.delay(1000); - const snapButton = await driver.findElement('#connectErrorSnap'); + const snapButton = await driver.findElement('#connecterrors'); await driver.scrollToElement(snapButton); await driver.delay(1000); - await driver.clickElement('#connectErrorSnap'); + await driver.clickElement('#connecterrors'); await driver.delay(1000); // switch to metamask extension and click connect @@ -72,8 +72,8 @@ describe('Test Snap Error', function () { // wait for npm installation success await driver.waitForSelector({ - css: '#connectErrorSnap', - text: 'Reconnect to Error Snap', + css: '#connecterrors', + text: 'Reconnect to Errors Snap', }); // find and click on send error @@ -90,7 +90,7 @@ describe('Test Snap Error', function () { const text = await error.getText(); assert.equal( text.includes( - "Snap Error: 'random error inside'. Error Code: '-32603'", + "Snap Error: 'Random error inside a promise.'. Error Code: '-32603'", ), true, ); diff --git a/test/e2e/snaps/test-snap-ethprovider.spec.js b/test/e2e/snaps/test-snap-ethprovider.spec.js index 694c25aeffca..0baa9e805460 100644 --- a/test/e2e/snaps/test-snap-ethprovider.spec.js +++ b/test/e2e/snaps/test-snap-ethprovider.spec.js @@ -30,10 +30,12 @@ describe('Test Snap ethereum_provider', function () { // navigate to test snaps page and connect await driver.driver.get(TEST_SNAPS_WEBSITE_URL); await driver.delay(1000); - const snapButton = await driver.findElement('#connectEthproviderSnap'); + const snapButton = await driver.findElement( + '#connectethereum-provider', + ); await driver.scrollToElement(snapButton); await driver.delay(1000); - await driver.clickElement('#connectEthproviderSnap'); + await driver.clickElement('#connectethereum-provider'); await driver.delay(1000); // switch to metamask extension and click connect @@ -65,16 +67,16 @@ describe('Test Snap ethereum_provider', function () { tag: 'button', }); - // click send inputs on test snap page + // switch to test snap page await driver.switchToWindowWithTitle('Test Snaps', windowHandles); // wait for npm installation success await driver.waitForSelector({ - css: '#connectEthproviderSnap', - text: 'Reconnect to ethereum-provider Snap', + css: '#connectethereum-provider', + text: 'Reconnect to Ethereum Provider Snap', }); - // find and click on send test + // find and click on send get version const snapButton2 = await driver.findElement('#sendEthprovider'); await driver.scrollToElement(snapButton2); await driver.delay(500); @@ -83,7 +85,44 @@ describe('Test Snap ethereum_provider', function () { // check the results of the message signature using waitForSelector await driver.waitForSelector({ css: '#ethproviderResult', - text: 'true', + text: '"1337"', + }); + + // find and click on send get version + const snapButton3 = await driver.findElement( + '#sendEthproviderAccounts', + ); + await driver.scrollToElement(snapButton3); + await driver.delay(500); + await driver.clickElement('#sendEthproviderAccounts'); + + // switch to metamask window and click through confirmations + const windowHandles2 = await driver.waitUntilXWindowHandles( + 2, + 1000, + 10000, + ); + await driver.switchToWindowWithTitle( + 'MetaMask Notification', + windowHandles2, + ); + await driver.clickElement({ + text: 'Next', + tag: 'button', + }); + await driver.delay(500); + await driver.clickElement({ + text: 'Connect', + tag: 'button', + }); + + // switch to test snap page + await driver.switchToWindowWithTitle('Test Snaps', windowHandles); + + // check the results of the message signature using waitForSelector + await driver.waitForSelector({ + css: '#ethproviderResult', + text: '"0x5cfe73b6021e818b776b421b1c4db2474086a7e1"', }); }, ); diff --git a/test/e2e/snaps/test-snap-getentropy.spec.js b/test/e2e/snaps/test-snap-getentropy.spec.js index 8b5586d24d1b..de6ecc4dcf80 100644 --- a/test/e2e/snaps/test-snap-getentropy.spec.js +++ b/test/e2e/snaps/test-snap-getentropy.spec.js @@ -53,6 +53,8 @@ describe('Test Snap getEntropy', function () { await driver.waitForSelector({ text: 'Install' }); + await driver.clickElementSafe('[data-testid="snap-install-scroll"]'); + await driver.clickElement({ text: 'Install', tag: 'button', @@ -71,7 +73,7 @@ describe('Test Snap getEntropy', function () { // wait for npm installation success await driver.waitForSelector({ css: '#connectGetEntropySnap', - text: 'Reconnect to getEntropy Snap', + text: 'Reconnect to Get Entropy Snap', }); // find and click on send test @@ -100,7 +102,7 @@ describe('Test Snap getEntropy', function () { // check the results of the message signature using waitForSelector await driver.waitForSelector({ css: '#entropySignResult', - text: '"0xb9c20d675976e12c8bb53c3fd8fdff2dee11ad2b132eb453b5a8f35b0553c52d3bcac0fd3324d22ff0c53b3445ef48c119ba6435bc9bfb03234806719599aa6f6245593238c734bcf9d94d2873cacdd65a3176be3ae7e5b84f95fdd4487a395f"', + text: '"0x9341785782b512c86235612365f1076b16731ed9473beb4d0804c30b7fcc3a055aa7103b02dc64014d923220712dfbef023ddcf6327b313ea2dfd4d83dc5a53e1c5e7f4e10bce49830eded302294054df8a7a46e5b6cb3e50eec564ecba17941"', }); }, ); diff --git a/test/e2e/snaps/test-snap-installed.spec.js b/test/e2e/snaps/test-snap-installed.spec.js index 71614a6f040b..f3ee0ba6e937 100644 --- a/test/e2e/snaps/test-snap-installed.spec.js +++ b/test/e2e/snaps/test-snap-installed.spec.js @@ -30,10 +30,10 @@ describe('Test Snap Installed', function () { // navigate to test snaps page and connect await driver.openNewPage(TEST_SNAPS_WEBSITE_URL); await driver.delay(1000); - const confirmButton = await driver.findElement('#connectDialogSnap'); + const confirmButton = await driver.findElement('#connectdialogs'); await driver.scrollToElement(confirmButton); await driver.delay(500); - await driver.clickElement('#connectDialogSnap'); + await driver.clickElement('#connectdialogs'); await driver.delay(500); // switch to metamask extension and click connect @@ -70,14 +70,14 @@ describe('Test Snap Installed', function () { // wait for npm installation success await driver.waitForSelector({ - css: '#connectDialogSnap', - text: 'Reconnect to Dialog Snap', + css: '#connectdialogs', + text: 'Reconnect to Dialogs Snap', }); - const errorButton = await driver.findElement('#connectErrorSnap'); + const errorButton = await driver.findElement('#connecterrors'); await driver.scrollToElement(errorButton); await driver.delay(500); - await driver.clickElement('#connectErrorSnap'); + await driver.clickElement('#connecterrors'); // switch to metamask extension and click connect windowHandles = await driver.waitUntilXWindowHandles(3, 1000, 10000); @@ -109,7 +109,7 @@ describe('Test Snap Installed', function () { // wait for npm installation success await driver.waitForSelector({ css: '#installedSnapsResult', - text: 'npm:@metamask/test-snap-dialog, npm:@metamask/test-snap-error', + text: 'npm:@metamask/dialog-example-snap, npm:@metamask/error-example-snap', }); }, ); diff --git a/test/e2e/snaps/test-snap-manageAccount.spec.js b/test/e2e/snaps/test-snap-manageAccount.spec.js index 9ba5dce54ca5..44ca13dbc3f6 100644 --- a/test/e2e/snaps/test-snap-manageAccount.spec.js +++ b/test/e2e/snaps/test-snap-manageAccount.spec.js @@ -52,11 +52,7 @@ describe('Test Snap Account', function () { tag: 'button', }); - try { - await driver.clickElement('[data-testid="snap-install-scroll"]'); - } catch (_) { - console.log('Missing scroll'); - } + await driver.clickElementSafe('[data-testid="snap-install-scroll"]'); await driver.waitForSelector({ text: 'Install' }); diff --git a/test/e2e/snaps/test-snap-management.spec.js b/test/e2e/snaps/test-snap-management.spec.js index df520d30ac74..6af006bd9ab1 100644 --- a/test/e2e/snaps/test-snap-management.spec.js +++ b/test/e2e/snaps/test-snap-management.spec.js @@ -33,10 +33,10 @@ describe('Test Snap Management', function () { await driver.delay(1000); // find and scroll to the correct card and click first - const snapButton = await driver.findElement('#connectNotification'); + const snapButton = await driver.findElement('#connectnotifications'); await driver.scrollToElement(snapButton); await driver.delay(1000); - await driver.clickElement('#connectNotification'); + await driver.clickElement('#connectnotifications'); await driver.delay(1000); // switch to metamask extension and click connect @@ -91,7 +91,7 @@ describe('Test Snap Management', function () { // try to disable the snap await driver.clickElement({ - text: 'Notification Test Snap', + text: 'Notifications Example Snap', tag: 'p', }); await driver.clickElement('.toggle-button > div'); @@ -138,7 +138,7 @@ describe('Test Snap Management', function () { // try to remove snap await driver.clickElement({ - text: 'Remove Notification Test Snap', + text: 'Remove Notifications Example Snap', tag: 'p', }); await driver.delay(1000); diff --git a/test/e2e/snaps/test-snap-managestate.spec.js b/test/e2e/snaps/test-snap-managestate.spec.js index 5bcc9bcbb037..dbd4f0891153 100644 --- a/test/e2e/snaps/test-snap-managestate.spec.js +++ b/test/e2e/snaps/test-snap-managestate.spec.js @@ -34,10 +34,10 @@ describe('Test Snap manageState', function () { await driver.delay(1000); // find and scroll to the connect button and click it - const snapButton1 = await driver.findElement('#connectManageState'); + const snapButton1 = await driver.findElement('#connectmanage-state'); await driver.scrollToElement(snapButton1); await driver.delay(1000); - await driver.clickElement('#connectManageState'); + await driver.clickElement('#connectmanage-state'); await driver.delay(1000); // switch to metamask extension and click connect @@ -74,7 +74,7 @@ describe('Test Snap manageState', function () { // wait for npm installation success await driver.waitForSelector({ - css: '#connectManageState', + css: '#connectmanage-state', text: 'Reconnect to Manage State Snap', }); @@ -101,7 +101,7 @@ describe('Test Snap manageState', function () { ); assert.equal( await retrieveManageStateResult.getText(), - '{ "testState": [ "23" ] }', + '{ "items": [ "23" ] }', ); // click clear results @@ -121,7 +121,7 @@ describe('Test Snap manageState', function () { ); assert.equal( await retrieveManageStateResult2.getText(), - '{ "testState": [] }', + '{ "items": [] }', ); }, ); diff --git a/test/e2e/snaps/test-snap-networkaccess.spec.js b/test/e2e/snaps/test-snap-networkaccess.spec.js index e80012a55012..0a65386804fc 100644 --- a/test/e2e/snaps/test-snap-networkaccess.spec.js +++ b/test/e2e/snaps/test-snap-networkaccess.spec.js @@ -1,4 +1,3 @@ -const { strict: assert } = require('assert'); const { withFixtures } = require('../helpers'); const FixtureBuilder = require('../fixture-builder'); const { TEST_SNAPS_WEBSITE_URL } = require('./enums'); @@ -31,16 +30,14 @@ describe('Test Snap networkAccess', function () { // navigate to test snaps page and connect to dialog snap await driver.openNewPage(TEST_SNAPS_WEBSITE_URL); await driver.delay(1000); - const dialogButton = await driver.findElement( - '#connectNetworkAccessSnap', - ); + const dialogButton = await driver.findElement('#connectnetwork-access'); await driver.scrollToElement(dialogButton); await driver.delay(1000); - await driver.clickElement('#connectNetworkAccessSnap'); + await driver.clickElement('#connectnetwork-access'); await driver.delay(1000); // switch to metamask extension and click connect - let windowHandles = await driver.waitUntilXWindowHandles( + const windowHandles = await driver.waitUntilXWindowHandles( 3, 1000, 10000, @@ -73,32 +70,18 @@ describe('Test Snap networkAccess', function () { // wait for npm installation success await driver.waitForSelector({ - css: '#connectNetworkAccessSnap', - text: 'Reconnect to networkAccess Snap', + css: '#connectnetwork-access', + text: 'Reconnect to Network Access Snap', }); // click on alert dialog await driver.clickElement('#sendNetworkAccessTest'); await driver.delay(500); - // switch to dialog popup - windowHandles = await driver.waitUntilXWindowHandles(3, 1000, 10000); - await driver.switchToWindowWithTitle( - 'MetaMask Notification', - windowHandles, - ); - await driver.delay(500); - - // check dialog contents - const result = await driver.findElement('.snap-ui-renderer__panel'); - await driver.scrollToElement(result); - await driver.delay(500); - assert.equal(await result.getText(), 'FETCHED_SUCCESSFULLY'); - - // click ok button - await driver.clickElement({ - text: 'OK', - tag: 'button', + // check for result correctness + await driver.waitForSelector({ + css: '#networkAccessResult', + text: '"hello": "world"', }); }, ); diff --git a/test/e2e/snaps/test-snap-notification.spec.js b/test/e2e/snaps/test-snap-notification.spec.js index d53fe06b9c30..64587b9e76ab 100644 --- a/test/e2e/snaps/test-snap-notification.spec.js +++ b/test/e2e/snaps/test-snap-notification.spec.js @@ -33,10 +33,10 @@ describe('Test Snap Notification', function () { await driver.delay(1000); // find and scroll down to snapId5 and connect - const snapButton = await driver.findElement('#connectNotification'); + const snapButton = await driver.findElement('#connectnotifications'); await driver.scrollToElement(snapButton); await driver.delay(1000); - await driver.clickElement('#connectNotification'); + await driver.clickElement('#connectnotifications'); await driver.delay(1000); // switch to metamask extension and click connect @@ -74,8 +74,8 @@ describe('Test Snap Notification', function () { // wait for npm installation success await driver.waitForSelector({ - css: '#connectNotification', - text: 'Reconnect to Notification Snap', + css: '#connectnotifications', + text: 'Reconnect to Notifications Snap', }); await driver.clickElement('#sendInAppNotification'); @@ -113,7 +113,7 @@ describe('Test Snap Notification', function () { ); assert.equal( await notificationResultMessage.getText(), - 'TEST INAPP NOTIFICATION', + 'Hello from within MetaMask!', ); }, ); diff --git a/test/e2e/snaps/test-snap-rpc.spec.js b/test/e2e/snaps/test-snap-rpc.spec.js index 5fe574490592..2c955e9e7d6e 100644 --- a/test/e2e/snaps/test-snap-rpc.spec.js +++ b/test/e2e/snaps/test-snap-rpc.spec.js @@ -32,10 +32,10 @@ describe('Test Snap RPC', function () { await driver.delay(1000); // find and scroll to the bip32 test and connect - const snapButton1 = await driver.findElement('#connectBip32'); + const snapButton1 = await driver.findElement('#connectbip32'); await driver.scrollToElement(snapButton1); await driver.delay(1000); - await driver.clickElement('#connectBip32'); + await driver.clickElement('#connectbip32'); await driver.delay(1000); // switch to metamask extension and click connect @@ -84,10 +84,10 @@ describe('Test Snap RPC', function () { // switch back to test-snaps window await driver.switchToWindowWithTitle('Test Snaps', windowHandles); - const snapButton2 = await driver.findElement('#connectRpcSnap'); + const snapButton2 = await driver.findElement('#connectjson-rpc'); await driver.scrollToElement(snapButton2); await driver.delay(1000); - await driver.clickElement('#connectRpcSnap'); + await driver.clickElement('#connectjson-rpc'); await driver.delay(1000); windowHandles = await driver.waitUntilXWindowHandles(2, 1000, 10000); @@ -118,8 +118,8 @@ describe('Test Snap RPC', function () { // wait for npm installation success await driver.waitForSelector({ - css: '#connectRpcSnap', - text: 'Reconnect to RPC Snap', + css: '#connectjson-rpc', + text: 'Reconnect to JSON-RPC Snap', }); // click send inputs on test snap page diff --git a/test/e2e/snaps/test-snap-txinsights.spec.js b/test/e2e/snaps/test-snap-txinsights.spec.js index cb8bfc3b1192..4130abb50c9d 100644 --- a/test/e2e/snaps/test-snap-txinsights.spec.js +++ b/test/e2e/snaps/test-snap-txinsights.spec.js @@ -32,10 +32,12 @@ describe('Test Snap TxInsights', function () { await driver.delay(1000); // find and scroll to the bip32 test and connect - const snapButton1 = await driver.findElement('#connectInsightsSnap'); + const snapButton1 = await driver.findElement( + '#connecttransaction-insights', + ); await driver.scrollToElement(snapButton1); await driver.delay(1000); - await driver.clickElement('#connectInsightsSnap'); + await driver.clickElement('#connecttransaction-insights'); await driver.delay(1000); // switch to metamask extension and click connect @@ -100,18 +102,16 @@ describe('Test Snap TxInsights', function () { 'MetaMask Notification', windowHandles, ); - await driver.delay(1000); - await driver.clickElement({ - text: 'TxInsightsTest', - tag: 'button', - }); // check that txinsightstest tab contains the right info await driver.delay(1000); const txInsightsResult = await driver.findElement( '.snap-ui-renderer__content', ); - assert.equal(await txInsightsResult.getText(), 'Test: Successful'); + assert.equal( + await txInsightsResult.getText(), + 'Transaction type:\nERC-20', + ); }, ); }); diff --git a/test/e2e/snaps/test-snap-update.spec.js b/test/e2e/snaps/test-snap-update.spec.js index 485c87b669f7..ea8dcbc11962 100644 --- a/test/e2e/snaps/test-snap-update.spec.js +++ b/test/e2e/snaps/test-snap-update.spec.js @@ -127,7 +127,7 @@ describe('Test Snap update', function () { // look for the correct version text await driver.waitForSelector({ css: '#updateSnapVersion', - text: '"5.1.2"', + text: '"0.35.2-flask.1"', }); }, ); diff --git a/test/e2e/snaps/test-snap-wasm.spec.js b/test/e2e/snaps/test-snap-wasm.spec.js index 1af49492f252..f0e301ca53e5 100644 --- a/test/e2e/snaps/test-snap-wasm.spec.js +++ b/test/e2e/snaps/test-snap-wasm.spec.js @@ -30,10 +30,10 @@ describe('Test Snap WASM', function () { // navigate to test snaps page and connect await driver.openNewPage(TEST_SNAPS_WEBSITE_URL); await driver.delay(1000); - const snapButton = await driver.findElement('#connectWasmSnap'); + const snapButton = await driver.findElement('#connectwasm'); await driver.scrollToElement(snapButton); await driver.delay(1000); - await driver.clickElement('#connectWasmSnap'); + await driver.clickElement('#connectwasm'); await driver.delay(1000); // switch to metamask extension and click connect @@ -71,7 +71,7 @@ describe('Test Snap WASM', function () { // wait for npm installation success await driver.waitForSelector({ - css: '#connectWasmSnap', + css: '#connectwasm', text: 'Reconnect to WebAssembly Snap', }); diff --git a/test/e2e/tests/eth-sign.spec.js b/test/e2e/tests/eth-sign.spec.js index 26d585ea541e..682cb9f5e8cc 100644 --- a/test/e2e/tests/eth-sign.spec.js +++ b/test/e2e/tests/eth-sign.spec.js @@ -136,7 +136,7 @@ describe('Eth sign', function () { await driver.waitForSelector({ text: 'Reject 2 requests', - tag: 'a', + tag: 'button', }); await verifyAndAssertEthSign(driver, DAPP_URL, expectedEthSignMessage); diff --git a/test/e2e/tests/personal-sign.spec.js b/test/e2e/tests/personal-sign.spec.js index 10e37a7c70d2..780d84796e6c 100644 --- a/test/e2e/tests/personal-sign.spec.js +++ b/test/e2e/tests/personal-sign.spec.js @@ -102,7 +102,7 @@ describe('Personal sign', function () { await driver.waitForSelector({ text: 'Reject 2 requests', - tag: 'a', + tag: 'button', }); const personalMessageRow = await driver.findElement( diff --git a/test/e2e/tests/signature-request.spec.js b/test/e2e/tests/signature-request.spec.js index 9ef703389f26..375f643be807 100644 --- a/test/e2e/tests/signature-request.spec.js +++ b/test/e2e/tests/signature-request.spec.js @@ -160,7 +160,7 @@ describe('Sign Typed Data Signature Request', function () { await driver.waitForSelector({ text: 'Reject 2 requests', - tag: 'a', + tag: 'button', }); await verifyAndAssertSignTypedData( diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index f3e4ccb1f168..d6592c44fec6 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -249,6 +249,18 @@ class Driver { await element.click(); } + async clickElementSafe(rawLocator) { + // for instances where an element such as a scroll button does not + // show up because of render differences, proceed to the next step + // without causing a test failure, but provide a console log of why. + try { + const element = await this.findClickableElement(rawLocator); + await element.click(); + } catch (e) { + console.log(`Element ${rawLocator} not found (${e})`); + } + } + async clickPoint(rawLocator, x, y) { const element = await this.findElement(rawLocator); await this.driver 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 81e9e9063c97..66c87e1474dc 100644 --- a/ui/components/app/create-new-vault/create-new-vault.js +++ b/ui/components/app/create-new-vault/create-new-vault.js @@ -2,9 +2,8 @@ import React, { useCallback, useState } from 'react'; import PropTypes from 'prop-types'; 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 { BUTTON_VARIANT, Button, Text } from '../../component-library'; import SrpInput from '../srp-input'; import { PASSWORD_MIN_LENGTH } from '../../../helpers/constants/common'; @@ -144,9 +143,9 @@ export default function CreateNewVault({ diff --git a/ui/components/app/detected-token/detected-token.js b/ui/components/app/detected-token/detected-token.js index e9deaea9cf65..af64ee00e041 100644 --- a/ui/components/app/detected-token/detected-token.js +++ b/ui/components/app/detected-token/detected-token.js @@ -73,7 +73,7 @@ const DetectedToken = ({ setShowDetectedTokens }) => { token_symbol: importedToken.symbol, token_contract_address: importedToken.address, token_decimal_precision: importedToken.decimals, - source_connection_method: MetaMetricsTokenEventSource.Detected, + source: MetaMetricsTokenEventSource.Detected, token_standard: TokenStandard.ERC20, asset_type: AssetType.token, token_added_type: 'detected', diff --git a/ui/components/app/security-provider-banner-alert/__snapshots__/security-provider-banner-alert.test.js.snap b/ui/components/app/security-provider-banner-alert/__snapshots__/security-provider-banner-alert.test.js.snap new file mode 100644 index 000000000000..54139024ceb2 --- /dev/null +++ b/ui/components/app/security-provider-banner-alert/__snapshots__/security-provider-banner-alert.test.js.snap @@ -0,0 +1,73 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Security Provider Banner Alert should match snapshot 1`] = ` +
+
+ +
+
+ Malicious third party detected +
+

+ This is a description to warn the user of malicious or suspicious transactions. +

+
+
+ +

+ [seeDetails] +

+ +
+
+
    +
  • + List item +
  • +
  • + List item +
  • +
  • + List item +
  • +
+
+
+
+

+ + [securityProviderAdviceBy] +

+
+
+
+`; diff --git a/ui/components/app/security-provider-banner-alert/blockaid-banner-alert/__snapshots__/blockaid-banner-alert.test.js.snap b/ui/components/app/security-provider-banner-alert/blockaid-banner-alert/__snapshots__/blockaid-banner-alert.test.js.snap new file mode 100644 index 000000000000..ca18324d9563 --- /dev/null +++ b/ui/components/app/security-provider-banner-alert/blockaid-banner-alert/__snapshots__/blockaid-banner-alert.test.js.snap @@ -0,0 +1,179 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Blockaid Banner Alert should render 'danger' UI when ppomResponse.resultType is 'Malicious 1`] = ` +
+ +
+
+ This is a deceptive request +
+

+ If you approve this request, a third party known for scams might take all your assets. +

+

+ + + + Security advice by + + Blockaid + + + + +

+
+
+`; + +exports[`Blockaid Banner Alert should render 'warning' UI when ppomResponse.resultType is 'Warning 1`] = ` +
+ +
+
+ This is a deceptive request +
+

+ If you approve this request, a third party known for scams might take all your assets. +

+

+ + + + Security advice by + + Blockaid + + + + +

+
+
+`; + +exports[`Blockaid Banner Alert should render details when provided 1`] = ` +
+
+ +
+
+ This is a deceptive request +
+

+ If you approve this request, a third party known for scams might take all your assets. +

+
+
+ +

+ See details +

+ +
+
+
    +
  • + • + Operator is an EOA +
  • +
  • + • + Operator is untrusted according to previous activity +
  • +
+
+
+
+

+ + + + Security advice by + + Blockaid + + + + +

+
+
+
+`; diff --git a/ui/components/app/security-provider-banner-alert/blockaid-banner-alert/blockaid-banner-alert.js b/ui/components/app/security-provider-banner-alert/blockaid-banner-alert/blockaid-banner-alert.js new file mode 100644 index 000000000000..1ced5b8054c5 --- /dev/null +++ b/ui/components/app/security-provider-banner-alert/blockaid-banner-alert/blockaid-banner-alert.js @@ -0,0 +1,90 @@ +import React, { useContext } from 'react'; +import PropTypes from 'prop-types'; +import { captureException } from '@sentry/browser'; + +import { Text } from '../../../component-library'; +import { Severity } from '../../../../helpers/constants/design-system'; +import { I18nContext } from '../../../../contexts/i18n'; + +import { + BlockaidReason, + BlockaidResultType, + SecurityProvider, +} from '../../../../../shared/constants/security-provider'; +import SecurityProviderBannerAlert from '../security-provider-banner-alert'; + +/** Reason to description translation key mapping. Grouped by translations. */ +const REASON_TO_DESCRIPTION_TKEY = Object.freeze({ + [BlockaidReason.approvalFarming]: 'blockaidDescriptionApproveFarming', + [BlockaidReason.permitFarming]: 'blockaidDescriptionApproveFarming', + [BlockaidReason.setApprovalForAll]: 'blockaidDescriptionApproveFarming', + + [BlockaidReason.blurFarming]: 'blockaidDescriptionBlurFarming', + + [BlockaidReason.seaportFarming]: 'blockaidDescriptionSeaportFarming', + + [BlockaidReason.maliciousDomain]: 'blockaidDescriptionMaliciousDomain', + + [BlockaidReason.rawSignatureFarming]: 'blockaidDescriptionMightLoseAssets', + [BlockaidReason.tradeOrderFarming]: 'blockaidDescriptionMightLoseAssets', + [BlockaidReason.unfairTrade]: 'blockaidDescriptionMightLoseAssets', + + [BlockaidReason.rawNativeTokenTransfer]: 'blockaidDescriptionTransferFarming', + [BlockaidReason.transferFarming]: 'blockaidDescriptionTransferFarming', + [BlockaidReason.transferFromFarming]: 'blockaidDescriptionTransferFarming', + + [BlockaidReason.other]: 'blockaidDescriptionMightLoseAssets', +}); + +/** List of suspicious reason(s). Other reasons will be deemed as deceptive. */ +const SUSPCIOUS_REASON = [BlockaidReason.rawSignatureFarming]; + +function BlockaidBannerAlert({ + ppomResponse: { reason, resultType, features }, +}) { + const t = useContext(I18nContext); + + if (resultType === BlockaidResultType.Benign) { + return null; + } + + if (!REASON_TO_DESCRIPTION_TKEY[reason]) { + captureException(`BlockaidBannerAlert: Unidentified reason '${reason}'`); + } + + const description = t(REASON_TO_DESCRIPTION_TKEY[reason] || 'other'); + + const details = Boolean(features?.length) && ( + + {features.map((feature, i) => ( +
  • • {feature}
  • + ))} +
    + ); + + const severity = + resultType === BlockaidResultType.Malicious + ? Severity.Danger + : Severity.Warning; + + const title = + SUSPCIOUS_REASON.indexOf(reason) > -1 + ? t('blockaidTitleSuspicious') + : t('blockaidTitleDeceptive'); + + return ( + + ); +} + +BlockaidBannerAlert.propTypes = { + ppomResponse: PropTypes.object, +}; + +export default BlockaidBannerAlert; diff --git a/ui/components/app/security-provider-banner-alert/blockaid-banner-alert/blockaid-banner-alert.stories.js b/ui/components/app/security-provider-banner-alert/blockaid-banner-alert/blockaid-banner-alert.stories.js new file mode 100644 index 000000000000..c12130871633 --- /dev/null +++ b/ui/components/app/security-provider-banner-alert/blockaid-banner-alert/blockaid-banner-alert.stories.js @@ -0,0 +1,42 @@ +import React from 'react'; +import { + BlockaidReason, + BlockaidResultType, +} from '../../../../../shared/constants/security-provider'; +import BlockaidBannerAlert from '.'; + +const mockFeatures = [ + 'Operator is an EOA', + 'Operator is untrusted according to previous activity', +]; + +export default { + title: 'Components/App/SecurityProviderBannerAlert/BlockaidBannerAlert', + argTypes: { + features: { + control: 'array', + description: + 'ppomResponse.features value which is a list displayed as SecurityProviderBannerAlert details', + }, + reason: { + control: 'select', + options: Object.values(BlockaidReason), + description: 'ppomResponse.reason value', + }, + resultType: { + control: 'select', + options: Object.values(BlockaidResultType), + description: 'ppomResponse.resultType value', + }, + }, + args: { + features: mockFeatures, + reason: BlockaidReason.setApprovalForAll, + resultType: BlockaidResultType.Warning, + }, +}; + +export const DefaultStory = (args) => ( + +); +DefaultStory.storyName = 'Default'; diff --git a/ui/components/app/security-provider-banner-alert/blockaid-banner-alert/blockaid-banner-alert.test.js b/ui/components/app/security-provider-banner-alert/blockaid-banner-alert/blockaid-banner-alert.test.js new file mode 100644 index 000000000000..7e71886455e9 --- /dev/null +++ b/ui/components/app/security-provider-banner-alert/blockaid-banner-alert/blockaid-banner-alert.test.js @@ -0,0 +1,144 @@ +import React from 'react'; +import { renderWithLocalization } from '../../../../../test/lib/render-helpers'; +import { Severity } from '../../../../helpers/constants/design-system'; +import { + BlockaidReason, + BlockaidResultType, +} from '../../../../../shared/constants/security-provider'; +import BlockaidBannerAlert from '.'; + +const mockPpomResponse = { + resultType: BlockaidResultType.Warning, + reason: BlockaidReason.setApprovalForAll, + description: + 'A SetApprovalForAll request was made on {contract}. We found the operator {operator} to be malicious', + args: { + contract: '0xa7206d878c5c3871826dfdb42191c49b1d11f466', + operator: '0x92a3b9773b1763efa556f55ccbeb20441962d9b2', + }, +}; + +describe('Blockaid Banner Alert', () => { + it(`should not render when ppomResponse.resultType is '${BlockaidResultType.Benign}'`, () => { + const { container } = renderWithLocalization( + , + ); + + expect(container.querySelector('.mm-banner-alert')).toBeNull(); + }); + + it(`should render '${Severity.Danger}' UI when ppomResponse.resultType is '${BlockaidResultType.Malicious}`, () => { + const { container } = renderWithLocalization( + , + ); + const dangerBannerAlert = container.querySelector( + '.mm-banner-alert--severity-danger', + ); + + expect(dangerBannerAlert).toBeInTheDocument(); + expect(dangerBannerAlert).toMatchSnapshot(); + }); + + it(`should render '${Severity.Warning}' UI when ppomResponse.resultType is '${BlockaidResultType.Warning}`, () => { + const { container } = renderWithLocalization( + , + ); + const warningBannerAlert = container.querySelector( + '.mm-banner-alert--severity-warning', + ); + + expect(warningBannerAlert).toBeInTheDocument(); + expect(warningBannerAlert).toMatchSnapshot(); + }); + + it('should render title, "This is a deceptive request"', () => { + const { getByText } = renderWithLocalization( + , + ); + + expect(getByText('This is a deceptive request')).toBeInTheDocument(); + }); + + it('should render title, "This is a suspicious request", when the reason is "raw_signature_farming"', () => { + const { getByText } = renderWithLocalization( + , + ); + + expect(getByText('This is a suspicious request')).toBeInTheDocument(); + }); + + it('should render details when provided', () => { + const mockFeatures = [ + 'Operator is an EOA', + 'Operator is untrusted according to previous activity', + ]; + + const { container, getByText } = renderWithLocalization( + , + ); + + expect(container).toMatchSnapshot(); + expect(container.querySelector('.disclosure')).toBeInTheDocument(); + mockFeatures.forEach((feature) => { + expect(getByText(`• ${feature}`)).toBeInTheDocument(); + }); + }); + + describe('when rendering description', () => { + Object.entries({ + [BlockaidReason.approvalFarming]: + 'If you approve this request, a third party known for scams might take all your assets.', + [BlockaidReason.blurFarming]: + 'If you approve this request, someone can steal your assets listed on Blur.', + [BlockaidReason.maliciousDomain]: + "You're interacting with a malicious domain. If you approve this request, you might lose your assets.", + [BlockaidReason.other]: + 'If you approve this request, you might lose your assets.', + [BlockaidReason.permitFarming]: + 'If you approve this request, a third party known for scams might take all your assets.', + [BlockaidReason.rawNativeTokenTransfer]: + 'If you approve this request, a third party known for scams will take all your assets.', + [BlockaidReason.rawSignatureFarming]: + 'If you approve this request, you might lose your assets.', + [BlockaidReason.seaportFarming]: + 'If you approve this request, someone can steal your assets listed on OpenSea.', + [BlockaidReason.setApprovalForAll]: + 'If you approve this request, a third party known for scams might take all your assets.', + [BlockaidReason.tradeOrderFarming]: + 'If you approve this request, you might lose your assets.', + [BlockaidReason.transferFromFarming]: + 'If you approve this request, a third party known for scams will take all your assets.', + [BlockaidReason.transferFarming]: + 'If you approve this request, a third party known for scams will take all your assets.', + [BlockaidReason.unfairTrade]: + 'If you approve this request, you might lose your assets.', + }).forEach(([reason, expectedDescription]) => { + it(`should render for '${reason}' correctly`, () => { + const { getByText } = renderWithLocalization( + , + ); + + expect(getByText(expectedDescription)).toBeInTheDocument(); + }); + }); + }); +}); diff --git a/ui/components/app/security-provider-banner-alert/blockaid-banner-alert/index.js b/ui/components/app/security-provider-banner-alert/blockaid-banner-alert/index.js new file mode 100644 index 000000000000..693cf2748278 --- /dev/null +++ b/ui/components/app/security-provider-banner-alert/blockaid-banner-alert/index.js @@ -0,0 +1 @@ +export { default } from './blockaid-banner-alert'; diff --git a/ui/components/app/security-provider-banner-alert/index.js b/ui/components/app/security-provider-banner-alert/index.js new file mode 100644 index 000000000000..f89920127118 --- /dev/null +++ b/ui/components/app/security-provider-banner-alert/index.js @@ -0,0 +1 @@ +export { default } from './security-provider-banner-alert'; diff --git a/ui/components/app/security-provider-banner-alert/security-provider-banner-alert.js b/ui/components/app/security-provider-banner-alert/security-provider-banner-alert.js new file mode 100644 index 000000000000..f6046d4e9ed1 --- /dev/null +++ b/ui/components/app/security-provider-banner-alert/security-provider-banner-alert.js @@ -0,0 +1,104 @@ +import React, { useContext } from 'react'; +import PropTypes from 'prop-types'; +import { + BannerAlert, + ButtonLink, + Icon, + IconName, + IconSize, + Text, +} from '../../component-library'; +import Disclosure from '../../ui/disclosure'; +import { DisclosureVariant } from '../../ui/disclosure/disclosure.constants'; + +import { I18nContext } from '../../../contexts/i18n'; +import { + AlignItems, + Color, + IconColor, + Severity, + Size, + TextVariant, +} from '../../../helpers/constants/design-system'; + +import { + SecurityProvider, + SECURITY_PROVIDER_CONFIG, +} from '../../../../shared/constants/security-provider'; + +function SecurityProviderBannerAlert({ + description, + details, + provider, + severity, + title, +}) { + const t = useContext(I18nContext); + + return ( + + {description} + + {details && ( + + {details} + + )} + + + + {t('securityProviderAdviceBy', [ + + {t(SECURITY_PROVIDER_CONFIG[provider].tKeyName)} + , + ])} + + + ); +} + +SecurityProviderBannerAlert.propTypes = { + /** Description content that may be plain text or contain hyperlinks */ + description: PropTypes.oneOfType([PropTypes.string, PropTypes.element]) + .isRequired, + + /** Name of the security provider */ + provider: PropTypes.oneOfType(Object.values(SecurityProvider)).isRequired, + + /** Severity level */ + severity: PropTypes.oneOfType([Severity.Danger, Severity.Warning]).isRequired, + + /** Title to be passed as param */ + title: PropTypes.string.isRequired, + + /** + * Optional + */ + + /** Additional details to be displayed under the description */ + details: PropTypes.oneOfType([PropTypes.string, PropTypes.element]), +}; + +export default SecurityProviderBannerAlert; diff --git a/ui/components/app/security-provider-banner-alert/security-provider-banner-alert.stories.js b/ui/components/app/security-provider-banner-alert/security-provider-banner-alert.stories.js new file mode 100644 index 000000000000..c78ce3f8fefd --- /dev/null +++ b/ui/components/app/security-provider-banner-alert/security-provider-banner-alert.stories.js @@ -0,0 +1,87 @@ +import React from 'react'; +import { Severity } from '../../../helpers/constants/design-system'; +import { ButtonLink, BUTTON_LINK_SIZES, Text } from '../../component-library'; +import { SecurityProvider } from '../../../../shared/constants/security-provider'; +import SecurityProviderBannerAlert from './security-provider-banner-alert'; + +const mockPlainText = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sapien tellus, elementum sit ' + + 'amet laoreet vitae, semper in est. Nulla vel tristique felis. Donec non tellus eget neque cursus malesuada.'; + +const MockDescriptionWithLinks = () => ( + <> + Description shouldn’t repeat title. 1-3 lines. Can contain a{' '} + hyperlink. It can + also contain a toggle to enable progressive disclosure. + +); + +const MockDetailsList = () => ( + +
  • • List item
  • +
  • • List item
  • +
  • • List item
  • +
  • • List item
  • +
    +); + +export default { + title: 'Components/App/SecurityProviderBannerAlert', + argTypes: { + description: { + control: { + type: 'select', + }, + options: ['plainText', 'withLinks'], + mapping: { + plainText: mockPlainText, + withLinks: , + }, + }, + details: { + control: { + type: 'select', + }, + options: ['none', 'plainText', 'withList'], + mapping: { + none: null, + plainText: mockPlainText, + withList: , + }, + }, + provider: { + control: { + type: 'select', + }, + options: [Object.values(SecurityProvider)], + }, + severity: { + control: { + type: 'select', + }, + options: [Severity.Danger, Severity.Warning], + }, + title: { + control: 'text', + }, + }, + args: { + title: 'Title is sentence case no period', + description: , + details: , + provider: SecurityProvider.Blockaid, + }, +}; + +export const DefaultStory = (args) => ( + +); +DefaultStory.storyName = 'Default'; + +export const Danger = (args) => ( + +); + +export const Warning = (args) => ( + +); diff --git a/ui/components/app/security-provider-banner-alert/security-provider-banner-alert.test.js b/ui/components/app/security-provider-banner-alert/security-provider-banner-alert.test.js new file mode 100644 index 000000000000..c11a1202e2ce --- /dev/null +++ b/ui/components/app/security-provider-banner-alert/security-provider-banner-alert.test.js @@ -0,0 +1,61 @@ +import React from 'react'; +import { Severity } from '../../../helpers/constants/design-system'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import { SecurityProvider } from '../../../../shared/constants/security-provider'; +import SecurityProviderBannerAlert from '.'; + +const mockTitle = 'Malicious third party detected'; +const mockDescription = + 'This is a description to warn the user of malicious or suspicious transactions.'; +const mockDetails = ( +
      +
    • List item
    • +
    • List item
    • +
    • List item
    • +
    +); + +describe('Security Provider Banner Alert', () => { + it('should match snapshot', () => { + const { container } = renderWithProvider( + , + ); + + expect(container).toMatchSnapshot(); + }); + + it('should render', () => { + const { container, getByText } = renderWithProvider( + , + ); + + expect(getByText(mockTitle)).toBeInTheDocument(); + expect(getByText(mockDescription)).toBeInTheDocument(); + expect(container.querySelector('.disclosure')).toBeInTheDocument(); + }); + + it('should not render disclosure component if no details were provided', () => { + const { container } = renderWithProvider( + , + ); + + expect(container.querySelector('.disclosure')).not.toBeInTheDocument(); + }); +}); 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 6dc18e4a480a..52d3d86fd562 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 @@ -3,6 +3,9 @@ import PropTypes from 'prop-types'; import classnames from 'classnames'; import { ObjectInspector } from 'react-inspector'; import { ethErrors, serializeError } from 'eth-rpc-errors'; +///: BEGIN:ONLY_INCLUDE_IN(snaps) +import { SubjectType } from '@metamask/permission-controller'; +///: END:ONLY_INCLUDE_IN import LedgerInstructionField from '../ledger-instruction-field'; import { MESSAGE_TYPE } from '../../../../shared/constants/app'; import { @@ -14,7 +17,6 @@ import { } from '../../../helpers/utils/util'; import { stripHexPrefix } from '../../../../shared/modules/hexstring-utils'; import { isSuspiciousResponse } from '../../../../shared/modules/security-provider.utils'; -import Button from '../../ui/button'; import SiteOrigin from '../../ui/site-origin'; import Typography from '../../ui/typography/typography'; import { PageContainerFooter } from '../../ui/page-container'; @@ -23,6 +25,7 @@ import { FontWeight, TextAlign, TextColor, + Size, ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) IconColor, DISPLAY, @@ -31,13 +34,24 @@ import { BackgroundColor, ///: END:ONLY_INCLUDE_IN } from '../../../helpers/constants/design-system'; -import ConfirmPageContainerNavigation from '../confirm-page-container/confirm-page-container-navigation'; -import SecurityProviderBannerMessage from '../security-provider-banner-message/security-provider-banner-message'; +import { + ButtonLink, + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + Icon, + IconName, + Text, + ///: END:ONLY_INCLUDE_IN +} from '../../component-library'; ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) -import { Icon, IconName, Text } from '../../component-library'; import Box from '../../ui/box/box'; ///: END:ONLY_INCLUDE_IN +import ConfirmPageContainerNavigation from '../confirm-page-container/confirm-page-container-navigation'; +import SecurityProviderBannerMessage from '../security-provider-banner-message/security-provider-banner-message'; + import SignatureRequestHeader from '../signature-request-header'; +///: BEGIN:ONLY_INCLUDE_IN(snaps) +import SnapLegacyAuthorshipHeader from '../snaps/snap-legacy-authorship-header'; +///: END:ONLY_INCLUDE_IN import SignatureRequestOriginalWarning from './signature-request-original-warning'; export default class SignatureRequestOriginal extends Component { @@ -171,16 +185,31 @@ export default class SignatureRequestOriginal extends Component { }
    - + { + // Use legacy authorship header for snaps + ///: BEGIN:ONLY_INCLUDE_IN(snaps) + targetSubjectMetadata?.subjectType === SubjectType.Snap ? ( + + ) : ( + ///: END:ONLY_INCLUDE_IN + + ///: BEGIN:ONLY_INCLUDE_IN(snaps) + ) + ///: END:ONLY_INCLUDE_IN + }
    { @@ -295,9 +332,11 @@ export default class SignatureRequestOriginal extends Component { } ///: END:ONLY_INCLUDE_IN + ///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask) await resolvePendingApproval(txData.id); clearConfirmTransaction(); history.push(mostRecentOverviewPage); + ///: END:ONLY_INCLUDE_IN } }} disabled={ @@ -366,13 +405,13 @@ export default class SignatureRequestOriginal extends Component { )} {this.renderFooter()} {messagesCount > 1 ? ( - + ) : null} ); 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 b0f5e31719d5..8913c1aceaba 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,10 +17,7 @@ import { setPersonalMessageInProgress, } from '../../../store/institutional/institution-background'; import { getEnvironmentType } from '../../../../app/scripts/lib/util'; -import { - showCustodyConfirmLink, - checkForUnapprovedMessages, -} from '../../../store/institutional/institution-actions'; +import { showCustodyConfirmLink } from '../../../store/institutional/institution-actions'; import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app'; ///: END:ONLY_INCLUDE_IN import { @@ -30,7 +27,6 @@ import { unconfirmedMessagesHashSelector, getTotalUnapprovedMessagesCount, ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - unapprovedPersonalMsgsSelector, getAccountType, getSelectedAccount, ///: END:ONLY_INCLUDE_IN @@ -71,7 +67,6 @@ function mapStateToProps(state, ownProps) { accountType: getAccountType(state), isNotification: envType === ENVIRONMENT_TYPE_NOTIFICATION, selectedAccount: getSelectedAccount(state), - unapprovedPersonalMessages: unapprovedPersonalMsgsSelector(state), ///: END:ONLY_INCLUDE_IN }; } @@ -146,7 +141,6 @@ function mmiMapDispatchToProps(dispatch) { ), setWaitForConfirmDeepLinkDialog: (wait) => dispatch(mmiActions.setWaitForConfirmDeepLinkDialog(wait)), - goHome: () => dispatch(goHome()), clearConfirmTransaction: () => dispatch(clearConfirmTransaction()), showRejectTransactionsConfirmationModal: ({ onSubmit, @@ -185,7 +179,6 @@ function mergeProps(stateProps, dispatchProps, ownProps) { ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) accountType, isNotification, - unapprovedPersonalMessages, ///: END:ONLY_INCLUDE_IN ...otherStateProps } = stateProps; @@ -202,25 +195,17 @@ function mergeProps(stateProps, dispatchProps, ownProps) { const mmiOnSignCallback = async (_msgData) => { if (accountType === 'custody') { try { - let msgData = _msgData; - let id = _msgData.custodyId; - if (!_msgData.custodyId) { - msgData = checkForUnapprovedMessages( - _msgData, - unapprovedPersonalMessages, - ); - id = msgData.custodyId; - } + await dispatchProps.resolvePendingApproval(_msgData.id); + dispatchProps.completedTx(_msgData.id); + dispatchProps.showCustodianDeepLink({ - custodyId: id, + custodyId: null, fromAddress: fromAccount.address, closeNotification: isNotification, onDeepLinkFetched: () => undefined, onDeepLinkShown: () => undefined, }); - await dispatchProps.setMsgInProgress(msgData.metamaskId); await dispatchProps.setWaitForConfirmDeepLinkDialog(true); - await goHome(); } catch (err) { await dispatchProps.setWaitForConfirmDeepLinkDialog(true); await dispatchProps.showTransactionsFailedModal({ @@ -229,6 +214,10 @@ function mergeProps(stateProps, dispatchProps, ownProps) { operationFailed: true, }); } + } else { + // Non Custody accounts follow normal flow + await dispatchProps.resolvePendingApproval(_msgData.id); + dispatchProps.completedTx(_msgData.id); } }; ///: END:ONLY_INCLUDE_IN 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 ddd4319e56c4..e036cc414b35 100644 --- a/ui/components/app/signature-request-siwe/signature-request-siwe.js +++ b/ui/components/app/signature-request-siwe/signature-request-siwe.js @@ -50,7 +50,6 @@ export default function SignatureRequestSIWE({ txData }) { const t = useContext(I18nContext); const allAccounts = useSelector(accountsWithSendEtherInfoSelector); const subjectMetadata = useSelector(getSubjectMetadata); - const messagesCount = useSelector(getTotalUnapprovedMessagesCount); const messagesList = useSelector(unconfirmedMessagesHashSelector); const mostRecentOverviewPage = useSelector(getMostRecentOverviewPage); diff --git a/ui/components/app/signature-request/__snapshots__/signature-request.component.test.js.snap b/ui/components/app/signature-request/__snapshots__/signature-request.test.js.snap similarity index 91% rename from ui/components/app/signature-request/__snapshots__/signature-request.component.test.js.snap rename to ui/components/app/signature-request/__snapshots__/signature-request.test.js.snap index 0f677800422c..6e14a4b505a2 100644 --- a/ui/components/app/signature-request/__snapshots__/signature-request.component.test.js.snap +++ b/ui/components/app/signature-request/__snapshots__/signature-request.test.js.snap @@ -41,7 +41,7 @@ exports[`Signature Request Component render should match snapshot when we are us of - 1 + 0
    @@ -144,12 +144,12 @@ exports[`Signature Request Component render should match snapshot when we are us
    - Unknown private network + Localhost 8545
    - Antonio + John Doe
    @@ -165,9 +165,9 @@ exports[`Signature Request Component render should match snapshot when we are us align="end" class="mm-box mm-text mm-text--body-sm mm-text--font-weight-bold mm-box--color-text-default" > - 966.987986 + 0 - ABC + ETH @@ -179,56 +179,48 @@ exports[`Signature Request Component render should match snapshot when we are us class="signature-request__origin" >
    -
    -
    - - T - -
    -
    - test - + class="box mm-icon mm-icon--size-md box--display-inline-block box--flex-direction-row box--color-icon-default" + style="mask-image: url('./images/icons/global.svg');" + />
    +

    + test +

    -

    Signature request -

    +
    Only sign this message if you fully understand the content and trust the requesting site.
    - -
    - Verify third-party details -
    -
    +
    + Verify third-party details +
    + +
    + `; @@ -818,7 +816,7 @@ exports[`Signature Request Component render should match snapshot when we want t of - 1 + 0
    @@ -921,12 +919,12 @@ exports[`Signature Request Component render should match snapshot when we want t
    - Unknown private network + Localhost 8545
    - Antonio + John Doe
    @@ -942,9 +940,9 @@ exports[`Signature Request Component render should match snapshot when we want t align="end" class="mm-box mm-text mm-text--body-sm mm-text--font-weight-bold mm-box--color-text-default" > - 1515270.174798 + 0 - DEF + ETH @@ -956,56 +954,48 @@ exports[`Signature Request Component render should match snapshot when we want t class="signature-request__origin" >
    -
    -
    - - T - -
    -
    - test - + class="box mm-icon mm-icon--size-md box--display-inline-block box--flex-direction-row box--color-icon-default" + style="mask-image: url('./images/icons/global.svg');" + />
    +

    + test +

    -

    Signature request -

    +
    Only sign this message if you fully understand the content and trust the requesting site.
    - -
    - Verify third-party details -
    -
    +
    + Verify third-party details +
    + +
    + `; diff --git a/ui/components/app/signature-request/index.js b/ui/components/app/signature-request/index.js index 8a01d820eeee..18ba8b157a56 100644 --- a/ui/components/app/signature-request/index.js +++ b/ui/components/app/signature-request/index.js @@ -1 +1 @@ -export { default } from './signature-request.container'; +export { default } from './signature-request'; diff --git a/ui/components/app/signature-request/index.scss b/ui/components/app/signature-request/index.scss index 5cc2a0981e2e..5467f2a84fc7 100644 --- a/ui/components/app/signature-request/index.scss +++ b/ui/components/app/signature-request/index.scss @@ -14,7 +14,7 @@ border-radius: 8px; @include screen-sm-min { - max-height: 80vh; + max-height: max-content; min-height: 570px; flex: 0 0 auto; margin-left: auto; @@ -22,7 +22,7 @@ } &__reject-all-button { - margin-top: -15px; + padding-bottom: 20px; } &__origin { @@ -58,12 +58,6 @@ font-weight: 500; } - - p { - @include H6; - - color: var(--color-text-muted); - } } a.signature-request-content__verify-contract-details { diff --git a/ui/components/app/signature-request/signature-request.component.js b/ui/components/app/signature-request/signature-request.component.js deleted file mode 100644 index c0358b99d7e5..000000000000 --- a/ui/components/app/signature-request/signature-request.component.js +++ /dev/null @@ -1,427 +0,0 @@ -import React, { PureComponent } from 'react'; -import { memoize } from 'lodash'; -import PropTypes from 'prop-types'; -import { ethErrors, serializeError } from 'eth-rpc-errors'; -import LedgerInstructionField from '../ledger-instruction-field'; -import { - sanitizeMessage, - getURLHostName, - getNetworkNameFromProviderType, - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - shortenAddress, - ///: END:ONLY_INCLUDE_IN -} from '../../../helpers/utils/util'; -import { - MetaMetricsEventCategory, - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - MetaMetricsEventName, - ///: END:ONLY_INCLUDE_IN -} from '../../../../shared/constants/metametrics'; -import SiteOrigin from '../../ui/site-origin'; -import Button from '../../ui/button'; -import ContractDetailsModal from '../modals/contract-details-modal/contract-details-modal'; -import { - TextAlign, - TextColor, - TextVariant, - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - IconColor, - Display, - BlockSize, - BackgroundColor, - ///: END:ONLY_INCLUDE_IN -} from '../../../helpers/constants/design-system'; -import NetworkAccountBalanceHeader from '../network-account-balance-header'; -import { Numeric } from '../../../../shared/modules/Numeric'; -import { isSuspiciousResponse } from '../../../../shared/modules/security-provider.utils'; -import { EtherDenomination } from '../../../../shared/constants/common'; -import ConfirmPageContainerNavigation from '../confirm-page-container/confirm-page-container-navigation'; -import SecurityProviderBannerMessage from '../security-provider-banner-message/security-provider-banner-message'; -import { formatCurrency } from '../../../helpers/utils/confirm-tx.util'; -import { getValueFromWeiHex } from '../../../../shared/modules/conversion.utils'; - -import { - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - Box, - Icon, - IconName, - ///: END:ONLY_INCLUDE_IN - Text, -} from '../../component-library'; -import Footer from './signature-request-footer'; -import Message from './signature-request-message'; - -export default class SignatureRequest extends PureComponent { - static propTypes = { - /** - * The display content of transaction data - */ - txData: PropTypes.object.isRequired, - /** - * The display content of sender account - */ - fromAccount: PropTypes.shape({ - address: PropTypes.string.isRequired, - balance: PropTypes.string, - name: PropTypes.string, - }).isRequired, - /** - * Check if the wallet is ledget wallet or not - */ - isLedgerWallet: PropTypes.bool, - - /** - * Whether the hardware wallet requires a connection disables the sign button if true. - */ - hardwareWalletRequiresConnection: PropTypes.bool.isRequired, - /** - * Current network chainId - */ - chainId: PropTypes.string, - /** - * RPC prefs of the current network - */ - rpcPrefs: PropTypes.object, - nativeCurrency: PropTypes.string, - currentCurrency: PropTypes.string.isRequired, - conversionRate: PropTypes.number, - providerConfig: PropTypes.object, - subjectMetadata: PropTypes.object, - unapprovedMessagesCount: PropTypes.number, - clearConfirmTransaction: PropTypes.func.isRequired, - history: PropTypes.object, - mostRecentOverviewPage: PropTypes.string, - showRejectTransactionsConfirmationModal: PropTypes.func.isRequired, - cancelAllApprovals: PropTypes.func.isRequired, - resolvePendingApproval: PropTypes.func.isRequired, - rejectPendingApproval: PropTypes.func.isRequired, - completedTx: PropTypes.func.isRequired, - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - showCustodianDeepLink: PropTypes.func, - isNotification: PropTypes.bool, - mmiOnSignCallback: PropTypes.func, - // Used to show a warning if the signing account is not the selected account - // Largely relevant for contract wallet custodians - selectedAccount: PropTypes.object, - ///: END:ONLY_INCLUDE_IN - }; - - static contextTypes = { - t: PropTypes.func, - trackEvent: PropTypes.func, - }; - - state = { - hasScrolledMessage: false, - showContractDetails: false, - }; - - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - componentDidMount() { - if (this.props.txData.custodyId) { - this.props.showCustodianDeepLink({ - custodyId: this.props.txData.custodyId, - fromAddress: this.props.fromAccount.address, - closeNotification: this.props.isNotification, - onDeepLinkFetched: () => undefined, - onDeepLinkShown: () => { - this.context.trackEvent({ - category: MetaMetricsEventCategory.MMI, - event: MetaMetricsEventName.SignatureDeeplinkDisplayed, - }); - }, - }); - } - } - ///: END:ONLY_INCLUDE_IN - - setMessageRootRef(ref) { - this.messageRootRef = ref; - } - - formatWallet(wallet) { - return `${wallet.slice(0, 8)}...${wallet.slice( - wallet.length - 8, - wallet.length, - )}`; - } - - memoizedParseMessage = memoize((data) => { - const { message, domain = {}, primaryType, types } = JSON.parse(data); - const sanitizedMessage = sanitizeMessage(message, primaryType, types); - return { sanitizedMessage, domain, primaryType }; - }); - - handleCancelAll = () => { - const { - clearConfirmTransaction, - history, - mostRecentOverviewPage, - showRejectTransactionsConfirmationModal, - unapprovedMessagesCount, - cancelAllApprovals, - } = this.props; - - showRejectTransactionsConfirmationModal({ - unapprovedTxCount: unapprovedMessagesCount, - onSubmit: async () => { - await cancelAllApprovals(); - clearConfirmTransaction(); - history.push(mostRecentOverviewPage); - }, - }); - }; - - render() { - const { - providerConfig, - txData: { - msgParams: { data, origin, version }, - type, - id, - }, - fromAccount: { address, balance, name }, - isLedgerWallet, - hardwareWalletRequiresConnection, - chainId, - rpcPrefs, - txData, - subjectMetadata, - nativeCurrency, - currentCurrency, - conversionRate, - unapprovedMessagesCount, - resolvePendingApproval, - rejectPendingApproval, - completedTx, - } = this.props; - - const { t, trackEvent } = this.context; - const { - sanitizedMessage, - domain: { verifyingContract }, - primaryType, - } = this.memoizedParseMessage(data); - const rejectNText = t('rejectRequestsN', [unapprovedMessagesCount]); - const networkName = getNetworkNameFromProviderType(providerConfig.type); - const currentNetwork = - networkName === '' - ? providerConfig.nickname || t('unknownNetwork') - : t(networkName); - - const balanceInBaseAsset = conversionRate - ? formatCurrency( - getValueFromWeiHex({ - value: balance, - fromCurrency: nativeCurrency, - toCurrency: currentCurrency, - conversionRate, - numberOfDecimals: 6, - toDenomination: EtherDenomination.ETH, - }), - currentCurrency, - ) - : new Numeric(balance, 16, EtherDenomination.WEI) - .toDenomination(EtherDenomination.ETH) - .round(6) - .toBase(10) - .toString(); - - const onSign = async () => { - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - if (this.props.mmiOnSignCallback) { - await this.props.mmiOnSignCallback(txData); - return; - } - ///: END:ONLY_INCLUDE_IN - - await resolvePendingApproval(id); - completedTx(id); - - trackEvent({ - category: MetaMetricsEventCategory.Transactions, - event: 'Confirm', - properties: { - action: 'Sign Request', - legacy_event: true, - type, - version, - }, - }); - }; - - const onCancel = async () => { - await rejectPendingApproval( - id, - serializeError(ethErrors.provider.userRejectedRequest()), - ); - trackEvent({ - category: MetaMetricsEventCategory.Transactions, - event: 'Cancel', - properties: { - action: 'Sign Request', - legacy_event: true, - type, - version, - }, - }); - }; - - const messageIsScrollable = - this.messageRootRef?.scrollHeight > this.messageRootRef?.clientHeight; - - const targetSubjectMetadata = txData.msgParams.origin - ? subjectMetadata?.[txData.msgParams.origin] - : null; - - return ( -
    - -
    - -
    -
    - {isSuspiciousResponse(txData?.securityProviderResponse) && ( - - )} - - { - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - this.props.selectedAccount.address === address ? null : ( - - - - {this.context.t('mismatchAccount', [ - shortenAddress(this.props.selectedAccount.address), - shortenAddress(address), - ])} - - - ) - ///: END:ONLY_INCLUDE_IN - } - -
    - -
    - - - {this.context.t('sigRequest')} - - - {this.context.t('signatureRequestGuidance')} - - {verifyingContract ? ( -
    - -
    - ) : null} -
    - {isLedgerWallet ? ( -
    - -
    - ) : null} - this.setState({ hasScrolledMessage: true })} - setMessageRootRef={this.setMessageRootRef.bind(this)} - messageRootRef={this.messageRootRef} - messageIsScrollable={messageIsScrollable} - primaryType={primaryType} - /> -
    - {this.state.showContractDetails && ( - this.setState({ showContractDetails: false })} - isContractRequestingSignature - /> - )} - {unapprovedMessagesCount > 1 ? ( - - ) : null} -
    - ); - } -} diff --git a/ui/components/app/signature-request/signature-request.constants.js b/ui/components/app/signature-request/signature-request.constants.js deleted file mode 100644 index e17841a0c783..000000000000 --- a/ui/components/app/signature-request/signature-request.constants.js +++ /dev/null @@ -1,3 +0,0 @@ -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app'; - -export { ENVIRONMENT_TYPE_NOTIFICATION }; diff --git a/ui/components/app/signature-request/signature-request.container.js b/ui/components/app/signature-request/signature-request.container.js deleted file mode 100644 index 4653a972c429..000000000000 --- a/ui/components/app/signature-request/signature-request.container.js +++ /dev/null @@ -1,298 +0,0 @@ -import { connect } from 'react-redux'; -import { - accountsWithSendEtherInfoSelector, - doesAddressRequireLedgerHidConnection, - getCurrentChainId, - getRpcPrefsForCurrentProvider, - getSubjectMetadata, - unconfirmedMessagesHashSelector, - getTotalUnapprovedMessagesCount, - getCurrentCurrency, - getPreferences, - conversionRateSelector, - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - getAccountType, - getSelectedAccount, - unapprovedTypedMessagesSelector, - ///: END:ONLY_INCLUDE_IN -} from '../../../selectors'; -import { - isAddressLedger, - getNativeCurrency, - getProviderConfig, -} from '../../../ducks/metamask/metamask'; -import { getAccountByAddress, valuesFor } from '../../../helpers/utils/util'; -///: BEGIN:ONLY_INCLUDE_IN(build-mmi) -// eslint-disable-next-line import/order -import { showCustodianDeepLink } from '@metamask-institutional/extension'; -import { - mmiActionsFactory, - setTypedMessageInProgress, -} from '../../../store/institutional/institution-background'; -import { getEnvironmentType } from '../../../../app/scripts/lib/util'; -import { - showCustodyConfirmLink, - checkForUnapprovedMessages, -} from '../../../store/institutional/institution-actions'; -///: END:ONLY_INCLUDE_IN -import { - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - ENVIRONMENT_TYPE_NOTIFICATION, - ///: END:ONLY_INCLUDE_IN -} from '../../../../shared/constants/app'; - -import { - showModal, - resolvePendingApproval, - rejectPendingApproval, - rejectAllMessages, - completedTx, - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - goHome, - ///: END:ONLY_INCLUDE_IN -} from '../../../store/actions'; -import { getMostRecentOverviewPage } from '../../../ducks/history/history'; -import { clearConfirmTransaction } from '../../../ducks/confirm-transaction/confirm-transaction.duck'; -import SignatureRequest from './signature-request.component'; - -function mapStateToProps(state, ownProps) { - const { txData } = ownProps; - - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - const envType = getEnvironmentType(); - ///: END:ONLY_INCLUDE_IN - - const { - msgParams: { from }, - } = txData; - const providerConfig = getProviderConfig(state); - - const hardwareWalletRequiresConnection = - doesAddressRequireLedgerHidConnection(state, from); - const isLedgerWallet = isAddressLedger(state, from); - const chainId = getCurrentChainId(state); - const rpcPrefs = getRpcPrefsForCurrentProvider(state); - const unconfirmedMessagesList = unconfirmedMessagesHashSelector(state); - const unapprovedMessagesCount = getTotalUnapprovedMessagesCount(state); - const { useNativeCurrencyAsPrimaryCurrency } = getPreferences(state); - - return { - providerConfig, - isLedgerWallet, - hardwareWalletRequiresConnection, - chainId, - rpcPrefs, - unconfirmedMessagesList, - unapprovedMessagesCount, - mostRecentOverviewPage: getMostRecentOverviewPage(state), - nativeCurrency: getNativeCurrency(state), - currentCurrency: getCurrentCurrency(state), - conversionRate: useNativeCurrencyAsPrimaryCurrency - ? null - : conversionRateSelector(state), - subjectMetadata: getSubjectMetadata(state), - // not forwarded to component - allAccounts: accountsWithSendEtherInfoSelector(state), - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - accountType: getAccountType(state), - isNotification: envType === ENVIRONMENT_TYPE_NOTIFICATION, - selectedAccount: getSelectedAccount(state), - unapprovedTypedMessages: unapprovedTypedMessagesSelector(state), - ///: END:ONLY_INCLUDE_IN - }; -} - -let mapDispatchToProps = null; - -mapDispatchToProps = function (dispatch) { - return { - 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)); - }, - }; -}; - -///: 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, - isLedgerWallet, - hardwareWalletRequiresConnection, - chainId, - rpcPrefs, - nativeCurrency, - currentCurrency, - conversionRate, - providerConfig, - subjectMetadata, - unconfirmedMessagesList, - unapprovedMessagesCount, - mostRecentOverviewPage, - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - accountType, - isNotification, - unapprovedTypedMessages, - ///: END:ONLY_INCLUDE_IN - } = stateProps; - const { txData } = ownProps; - - const { - cancelAll: dispatchCancelAll, - cancelAllApprovals: dispatchCancelAllApprovals, - } = dispatchProps; - - const { - msgParams: { from }, - } = txData; - - const fromAccount = getAccountByAddress(allAccounts, from); - - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - const mmiOnSignCallback = async (_msgData) => { - if (accountType === 'custody') { - try { - let msgData = _msgData; - let id = _msgData.custodyId; - if (!_msgData.custodyId) { - msgData = checkForUnapprovedMessages( - _msgData, - unapprovedTypedMessages, - ); - id = msgData.custodyId; - } - dispatchProps.showCustodianDeepLink({ - custodyId: id, - fromAddress: fromAccount.address, - closeNotification: isNotification, - onDeepLinkFetched: () => undefined, - onDeepLinkShown: () => undefined, - }); - await dispatchProps.setMsgInProgress(msgData.metamaskId); - await dispatchProps.setWaitForConfirmDeepLinkDialog(true); - await goHome(); - } catch (err) { - await dispatchProps.setWaitForConfirmDeepLinkDialog(true); - await dispatchProps.showTransactionsFailedModal({ - errorMessage: err.message, - closeNotification: true, - operationFailed: true, - }); - } - } - }; - ///: END:ONLY_INCLUDE_IN - - return { - ...ownProps, - ...dispatchProps, - fromAccount, - txData, - isLedgerWallet, - hardwareWalletRequiresConnection, - chainId, - rpcPrefs, - nativeCurrency, - currentCurrency, - conversionRate, - providerConfig, - subjectMetadata, - unapprovedMessagesCount, - mostRecentOverviewPage, - cancelAll: () => dispatchCancelAll(valuesFor(unconfirmedMessagesList)), - cancelAllApprovals: () => - dispatchCancelAllApprovals(valuesFor(unconfirmedMessagesList)), - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - mmiOnSignCallback, - ///: END:ONLY_INCLUDE_IN - }; -} - -export default connect( - mapStateToProps, - mapDispatchToProps, - mergeProps, -)(SignatureRequest); diff --git a/ui/components/app/signature-request/signature-request.container.test.js b/ui/components/app/signature-request/signature-request.container.test.js deleted file mode 100644 index f7c5522cec5d..000000000000 --- a/ui/components/app/signature-request/signature-request.container.test.js +++ /dev/null @@ -1,237 +0,0 @@ -import React from 'react'; -import sinon from 'sinon'; -import { fireEvent, screen, act } from '@testing-library/react'; -import configureMockStore from 'redux-mock-store'; -import { renderWithProvider } from '../../../../test/lib/render-helpers'; -import SignatureRequest from './signature-request.container'; - -const mockStoreWithEth = { - metamask: { - tokenList: { - '0x514910771af9ca656af840dff83e8264ecf986ca': { - address: '0x514910771af9ca656af840dff83e8264ecf986ca', - symbol: 'LINK', - decimals: 18, - name: 'ChainLink Token', - iconUrl: 'https://crypto.com/price/coin-data/icon/LINK/color_icon.png', - aggregators: [ - 'Aave', - 'Bancor', - 'CMC', - 'Crypto.com', - 'CoinGecko', - '1inch', - 'Paraswap', - 'PMM', - 'Zapper', - 'Zerion', - '0x', - ], - occurrences: 12, - unlisted: false, - }, - }, - identities: { - '0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e': { - name: 'Account 2', - address: '0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e', - }, - }, - addressBook: { - undefined: { - 0: { - address: '0x39a4e4Af7cCB654dB9500F258c64781c8FbD39F0', - name: '', - isEns: false, - }, - }, - }, - providerConfig: { - type: 'rpc', - }, - preferences: { - useNativeCurrencyAsPrimaryCurrency: true, - }, - accounts: { - '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5': { - address: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', - balance: '0x03', - }, - }, - cachedBalances: {}, - unapprovedDecryptMsgs: {}, - unapprovedEncryptionPublicKeyMsgs: {}, - unconfirmedTransactions: {}, - selectedAddress: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', - nativeCurrency: 'ETH', - currentCurrency: 'usd', - conversionRate: 231.06, - }, -}; - -const mockStoreWithFiat = { - ...mockStoreWithEth, - preferences: { - useNativeCurrencyAsPrimaryCurrency: false, - }, -}; -describe('Signature Request', () => { - const propsWithEth = { - fromAccount: { - address: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', - balance: '0x346ba7725f412cbfdb', - name: 'John Doe', - }, - history: { - push: sinon.spy(), - }, - hardwareWalletRequiresConnection: false, - mostRecentOverviewPage: '/', - clearConfirmTransaction: sinon.spy(), - cancelMessage: sinon.spy(), - cancel: sinon.stub().resolves(), - rejectPendingApproval: sinon.stub().resolves(), - showRejectTransactionsConfirmationModal: sinon.stub().resolves(), - cancelAll: sinon.stub().resolves(), - providerConfig: { - type: 'rpc', - }, - unapprovedMessagesCount: 2, - sign: sinon.stub().resolves(), - cancelAllApprovals: sinon.stub().resolves(), - resolvePendingApproval: sinon.stub().resolves(), - completedTx: sinon.stub().resolves(), - txData: { - msgParams: { - id: 1, - data: '{"types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Person":[{"name":"name","type":"string"},{"name":"wallet","type":"address"}],"Mail":[{"name":"from","type":"Person"},{"name":"to","type":"Person"},{"name":"contents","type":"string"}]},"primaryType":"Mail","domain":{"name":"Ether Mail","version":"1","chainId":"4","verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"},"message":{"from":{"name":"Cow","wallet":"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"},"to":{"name":"Bob","wallet":"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"},"contents":"Hello, Bob!"}}', - from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', - origin: 'test.domain', - }, - status: 'unapproved', - time: 1, - type: 'eth_sign', - }, - nativeCurrency: 'ETH', - currentCurrency: 'usd', - conversionRate: null, - selectedAccount: { - address: '0x123456789abcdef', - }, - }; - - const propsWithFiat = { - ...propsWithEth, - conversionRate: 156.72, - }; - - describe('Render with different currencies', () => { - it('should render balance with ETH when conversionRate is not provided', () => { - const store = configureMockStore()(mockStoreWithEth); - renderWithProvider( - , - store, - ); - expect( - screen.getByTestId('request-signature-account').textContent, - ).toMatchInlineSnapshot( - `"UUnknown private networkJohn DoeBalance966.987986 ETH"`, - ); - }); - - it('should render balance with fiat when conversionRate not provided', () => { - const store = configureMockStore()(mockStoreWithFiat); - renderWithProvider( - , - store, - ); - expect( - screen.getByTestId('request-signature-account').textContent, - ).toMatchInlineSnapshot( - `"UUnknown private networkJohn DoeBalance$151,546.36 USD"`, - ); - }); - }); - - describe('functionality check', () => { - beforeEach(() => { - const store = configureMockStore()(mockStoreWithFiat); - renderWithProvider( - , - store, - ); - }); - - afterEach(() => { - propsWithFiat.clearConfirmTransaction.resetHistory(); - }); - - it('cancel', async () => { - const cancelButton = screen.getByTestId('page-container-footer-cancel'); - await act(() => { - fireEvent.click(cancelButton); - }); - expect(propsWithFiat.rejectPendingApproval.calledOnce).toStrictEqual( - true, - ); - }); - - it('sign', async () => { - const signButton = screen.getByTestId('page-container-footer-next'); - await act(() => { - fireEvent.click(signButton); - }); - expect(propsWithFiat.resolvePendingApproval.calledOnce).toStrictEqual( - true, - ); - }); - - it('have user warning', () => { - const warningText = screen.getByText( - 'Only sign this message if you fully understand the content and trust the requesting site.', - ); - - expect(warningText).toBeInTheDocument(); - }); - }); - - describe('contract details', () => { - let store; - beforeEach(() => { - store = configureMockStore()(mockStoreWithFiat); - }); - it('shows verify contract details link when verifyingContract is set', () => { - renderWithProvider( - , - store, - ); - const verifyingContractLink = screen.getByTestId( - 'verify-contract-details', - ); - expect(verifyingContractLink).toBeInTheDocument(); - }); - - it('should not show verify contract details link when verifyingContract is not set', () => { - const newData = JSON.parse(propsWithFiat.txData.msgParams.data); - delete newData.domain.verifyingContract; - - const newProps = { - ...propsWithFiat, - txData: { - ...propsWithFiat.txData, - msgParams: { - ...propsWithFiat.txData.msgParams, - data: JSON.stringify(newData), - }, - }, - }; - - renderWithProvider( - , - store, - ); - - expect(screen.queryByTestId('verify-contract-details')).toBeNull(); - }); - }); -}); diff --git a/ui/components/app/signature-request/signature-request.js b/ui/components/app/signature-request/signature-request.js new file mode 100644 index 000000000000..0f00b5d9bee8 --- /dev/null +++ b/ui/components/app/signature-request/signature-request.js @@ -0,0 +1,383 @@ +import React, { useContext, useState, useEffect } from 'react'; +import { + useDispatch, + useSelector, + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + shallowEqual, + ///: END:ONLY_INCLUDE_IN +} from 'react-redux'; +import PropTypes from 'prop-types'; +import { memoize } from 'lodash'; +import { ethErrors, serializeError } from 'eth-rpc-errors'; +///: BEGIN:ONLY_INCLUDE_IN(build-mmi) +import { showCustodianDeepLink } from '@metamask-institutional/extension'; +///: END:ONLY_INCLUDE_IN +import { + resolvePendingApproval, + rejectPendingApproval, + completedTx, +} from '../../../store/actions'; +import { + doesAddressRequireLedgerHidConnection, + getSubjectMetadata, + getTotalUnapprovedMessagesCount, + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + accountsWithSendEtherInfoSelector, + getSelectedAccount, + getAccountType, + ///: END:ONLY_INCLUDE_IN +} from '../../../selectors'; +import { + getProviderConfig, + isAddressLedger, +} from '../../../ducks/metamask/metamask'; +import { + sanitizeMessage, + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + getAccountByAddress, + shortenAddress, + ///: END:ONLY_INCLUDE_IN +} from '../../../helpers/utils/util'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { useRejectTransactionModal } from '../../../hooks/useRejectTransactionModal'; + +import { ConfirmPageContainerNavigation } from '../confirm-page-container'; +import SignatureRequestHeader from '../signature-request-header/signature-request-header'; +import SecurityProviderBannerMessage from '../security-provider-banner-message'; +import LedgerInstructionField from '../ledger-instruction-field'; +import ContractDetailsModal from '../modals/contract-details-modal'; +import { MetaMetricsContext } from '../../../contexts/metametrics'; +import { + MetaMetricsEventCategory, + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + MetaMetricsEventName, + ///: END:ONLY_INCLUDE_IN +} from '../../../../shared/constants/metametrics'; +import { SECURITY_PROVIDER_MESSAGE_SEVERITY } from '../../../../shared/constants/security-provider'; + +import { + TextAlign, + TextColor, + TextVariant, + Size, + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + IconColor, + BackgroundColor, + Display, + BlockSize, + ///: END:ONLY_INCLUDE_IN +} from '../../../helpers/constants/design-system'; +import { + BUTTON_VARIANT, + Button, + ButtonLink, + TagUrl, + Text, + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + Icon, + IconName, + ///: END:ONLY_INCLUDE_IN +} from '../../component-library'; + +///: BEGIN:ONLY_INCLUDE_IN(build-mmi) +// eslint-disable-next-line import/order +import Box from '../../ui/box/box'; +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { mmiActionsFactory } from '../../../store/institutional/institution-background'; +import { showCustodyConfirmLink } from '../../../store/institutional/institution-actions'; +import { useMMICustodySignMessage } from '../../../hooks/useMMICustodySignMessage'; +///: END:ONLY_INCLUDE_IN + +import Message from './signature-request-message'; +import Footer from './signature-request-footer'; + +const SignatureRequest = ({ txData }) => { + const trackEvent = useContext(MetaMetricsContext); + const dispatch = useDispatch(); + const t = useI18nContext(); + + const [hasScrolledMessage, setHasScrolledMessage] = useState(false); + const [showContractDetails, setShowContractDetails] = useState(false); + const [messageRootRef, setMessageRootRef] = useState(null); + const [messageIsScrollable, setMessageIsScrollable] = useState(false); + + const { + id, + type, + msgParams: { from, data, origin, version }, + } = txData; + + // not forwarded to component + const hardwareWalletRequiresConnection = useSelector((state) => + doesAddressRequireLedgerHidConnection(state, from), + ); + const { chainId, rpcPrefs } = useSelector(getProviderConfig); + const unapprovedMessagesCount = useSelector(getTotalUnapprovedMessagesCount); + const subjectMetadata = useSelector(getSubjectMetadata); + const isLedgerWallet = useSelector((state) => isAddressLedger(state, from)); + const { handleCancelAll } = useRejectTransactionModal(); + + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + // Used to show a warning if the signing account is not the selected account + // Largely relevant for contract wallet custodians + const selectedAccount = useSelector(getSelectedAccount); + const mmiActions = mmiActionsFactory(); + const accountType = useSelector(getAccountType); + const isNotification = getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION; + const allAccounts = useSelector( + accountsWithSendEtherInfoSelector, + shallowEqual, + ); + const { address } = getAccountByAddress(allAccounts, from) || {}; + const { custodySignFn } = useMMICustodySignMessage(); + ///: END:ONLY_INCLUDE_IN + + useEffect(() => { + setMessageIsScrollable( + messageRootRef?.scrollHeight > messageRootRef?.clientHeight, + ); + }, [messageRootRef]); + + const targetSubjectMetadata = subjectMetadata?.[origin] || null; + + const parseMessage = memoize((dataToParse) => { + const { + message, + domain = {}, + primaryType, + types, + } = JSON.parse(dataToParse); + const sanitizedMessage = sanitizeMessage(message, primaryType, types); + return { sanitizedMessage, domain, primaryType }; + }); + + const onSign = async () => { + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + if (accountType === 'custody') { + await custodySignFn(txData); + return; + } + ///: END:ONLY_INCLUDE_IN + + ///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask) + await dispatch(resolvePendingApproval(id)); + completedTx(id); + ///: END:ONLY_INCLUDE_IN + + trackEvent({ + category: MetaMetricsEventCategory.Transactions, + event: 'Confirm', + properties: { + action: 'Sign Request', + legacy_event: true, + type, + version, + }, + }); + }; + + const onCancel = async () => { + await dispatch( + rejectPendingApproval( + id, + serializeError(ethErrors.provider.userRejectedRequest()), + ), + ); + trackEvent({ + category: MetaMetricsEventCategory.Transactions, + event: 'Cancel', + properties: { + action: 'Sign Request', + legacy_event: true, + type, + version, + }, + }); + }; + + const { + sanitizedMessage, + domain: { verifyingContract }, + primaryType, + } = parseMessage(data); + + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + useEffect(() => { + if (txData.custodyId) { + showCustodianDeepLink({ + dispatch, + mmiActions, + txId: undefined, + custodyId: txData.custodyId, + fromAddress: address, + isSignature: true, + closeNotification: isNotification, + onDeepLinkFetched: () => undefined, + onDeepLinkShown: () => { + trackEvent({ + category: MetaMetricsEventCategory.MMI, + event: MetaMetricsEventName.SignatureDeeplinkDisplayed, + }); + }, + showCustodyConfirmLink, + }); + } + }, [ + dispatch, + mmiActions, + txData.custodyId, + address, + isNotification, + trackEvent, + ]); + ///: END:ONLY_INCLUDE_IN + + return ( +
    + +
    + +
    +
    + {(txData?.securityProviderResponse?.flagAsDangerous !== undefined && + txData?.securityProviderResponse?.flagAsDangerous !== + SECURITY_PROVIDER_MESSAGE_SEVERITY.NOT_MALICIOUS) || + (txData?.securityProviderResponse && + Object.keys(txData.securityProviderResponse).length === 0) ? ( + + ) : null} + { + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + selectedAccount.address === address ? null : ( + + + + {t('mismatchAccount', [ + shortenAddress(selectedAccount.address), + shortenAddress(address), + ])} + + + ) + ///: END:ONLY_INCLUDE_IN + } +
    + +
    + + {t('sigRequest')} + + + {t('signatureRequestGuidance')} + + {verifyingContract ? ( +
    + +
    + ) : null} +
    + {isLedgerWallet ? ( +
    + +
    + ) : null} + setHasScrolledMessage(true)} + setMessageRootRef={setMessageRootRef} + messageRootRef={messageRootRef} + messageIsScrollable={messageIsScrollable} + primaryType={primaryType} + /> +
    + {showContractDetails && ( + setShowContractDetails(false)} + isContractRequestingSignature + /> + )} + {unapprovedMessagesCount > 1 ? ( + + {t('rejectRequestsN', [unapprovedMessagesCount])} + + ) : null} +
    + ); +}; + +SignatureRequest.propTypes = { + txData: PropTypes.object, +}; + +export default SignatureRequest; diff --git a/ui/components/app/signature-request/signature-request.stories.js b/ui/components/app/signature-request/signature-request.stories.js index 1fc2e555baa1..c74ac745796d 100644 --- a/ui/components/app/signature-request/signature-request.stories.js +++ b/ui/components/app/signature-request/signature-request.stories.js @@ -1,14 +1,22 @@ import React from 'react'; +import { Provider } from 'react-redux'; +import configureStore from '../../../store/store'; import testData from '../../../../.storybook/test-data'; import README from './README.mdx'; -import SignatureRequest from './signature-request.component'; +import SignatureRequest from './signature-request'; -const [MOCK_PRIMARY_IDENTITY, MOCK_SECONDARY_IDENTITY] = Object.values( - testData.metamask.identities, -); +const store = configureStore({ + ...testData, + metamask: { + ...testData.metamask, + selectedAddress: '0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e', + }, +}); export default { title: 'Components/App/SignatureRequest', + decorators: [(story) => {story()}], + component: SignatureRequest, parameters: { docs: { @@ -17,22 +25,6 @@ export default { }, argTypes: { txData: { control: 'object' }, - fromAccount: { - table: { - address: { control: 'text' }, - balance: { control: 'text' }, - name: { control: 'text' }, - }, - }, - hardwareWalletRequiresConnection: { control: 'boolean' }, - isLedgerWallet: { control: 'boolean' }, - clearConfirmTransaction: { action: 'Clean Confirm' }, - cancel: { action: 'Cancel' }, - sign: { action: 'Sign' }, - showRejectTransactionsConfirmationModal: { - action: 'showRejectTransactionsConfirmationModal', - }, - cancelAll: { action: 'cancelAll' }, }, }; @@ -45,6 +37,7 @@ DefaultStory.storyName = 'Default'; DefaultStory.args = { txData: { msgParams: { + from: '0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e', data: JSON.stringify({ domain: { name: 'happydapp.website', @@ -79,11 +72,6 @@ DefaultStory.args = { origin: 'https://happydapp.website/', }, }, - fromAccount: MOCK_PRIMARY_IDENTITY, - providerConfig: { name: 'Goerli ETH' }, - selectedAccount: MOCK_PRIMARY_IDENTITY, - hardwareWalletRequiresConnection: false, - currentCurrency: 'usd', }; export const AccountMismatchStory = (args) => { @@ -94,5 +82,10 @@ AccountMismatchStory.storyName = 'AccountMismatch'; AccountMismatchStory.args = { ...DefaultStory.args, - selectedAccount: MOCK_SECONDARY_IDENTITY, + txData: { + msgParams: { + ...DefaultStory.args.txData.msgParams, + from: '0x64a845a5b02460acf8a3d84503b0d68d028b4bb4', + }, + }, }; diff --git a/ui/components/app/signature-request/signature-request.component.test.js b/ui/components/app/signature-request/signature-request.test.js similarity index 67% rename from ui/components/app/signature-request/signature-request.component.test.js rename to ui/components/app/signature-request/signature-request.test.js index 81f18932a3e3..4c500d3fdb3e 100644 --- a/ui/components/app/signature-request/signature-request.component.test.js +++ b/ui/components/app/signature-request/signature-request.test.js @@ -1,33 +1,98 @@ import React from 'react'; +import { useSelector } from 'react-redux'; import { fireEvent } from '@testing-library/react'; import configureMockStore from 'redux-mock-store'; import mockState from '../../../../test/data/mock-state.json'; import { renderWithProvider } from '../../../../test/lib/render-helpers'; import { SECURITY_PROVIDER_MESSAGE_SEVERITY } from '../../../../shared/constants/security-provider'; -import SignatureRequest from './signature-request.component'; +import { + getNativeCurrency, + getProviderConfig, +} from '../../../ducks/metamask/metamask'; +import { + accountsWithSendEtherInfoSelector, + conversionRateSelector, + getCurrentCurrency, + getMemoizedAddressBook, + getMemoizedMetaMaskIdentities, + getPreferences, + getSelectedAccount, + getTotalUnapprovedMessagesCount, + unconfirmedTransactionsHashSelector, +} from '../../../selectors'; +import SignatureRequest from './signature-request'; const baseProps = { - hardwareWalletRequiresConnection: false, - clearConfirmTransaction: () => undefined, - cancel: () => undefined, - cancelAll: () => undefined, - mostRecentOverviewPage: '/', - showRejectTransactionsConfirmationModal: () => undefined, - sign: () => undefined, - history: { push: '/' }, - providerConfig: { type: 'rpc' }, - nativeCurrency: 'ABC', - currentCurrency: 'def', - fromAccount: { - address: '0x123456789abcdef', - balance: '0x346ba7725f412cbfdb', - name: 'Antonio', - }, - selectedAccount: { - address: '0x123456789abcdef', + clearConfirmTransaction: () => jest.fn(), + cancel: () => jest.fn(), + cancelAll: () => jest.fn(), + showRejectTransactionsConfirmationModal: () => jest.fn(), + sign: () => jest.fn(), +}; +const mockStore = { + metamask: { + providerConfig: { + chainId: '0x539', + nickname: 'Localhost 8545', + rpcPrefs: {}, + rpcUrl: 'http://localhost:8545', + ticker: 'ETH', + type: 'rpc', + }, + preferences: { + useNativeCurrencyAsPrimaryCurrency: true, + }, + accounts: { + '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5': { + address: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', + balance: '0x03', + name: 'John Doe', + }, + }, + selectedAddress: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', + nativeCurrency: 'ETH', + currentCurrency: 'usd', + conversionRate: null, + unapprovedTypedMessagesCount: 2, }, }; +jest.mock('react-redux', () => { + const actual = jest.requireActual('react-redux'); + + return { + ...actual, + useSelector: jest.fn(), + useDispatch: () => jest.fn(), + }; +}); +const generateUseSelectorRouter = (opts) => (selector) => { + switch (selector) { + case getProviderConfig: + return opts.metamask.providerConfig; + case getCurrentCurrency: + return opts.metamask.currentCurrency; + case getNativeCurrency: + return opts.metamask.nativeCurrency; + case getTotalUnapprovedMessagesCount: + return opts.metamask.unapprovedTypedMessagesCount; + case getPreferences: + return opts.metamask.preferences; + case conversionRateSelector: + return opts.metamask.conversionRate; + case getSelectedAccount: + return opts.metamask.accounts[opts.metamask.selectedAddress]; + case getMemoizedAddressBook: + return []; + case accountsWithSendEtherInfoSelector: + return Object.values(opts.metamask.accounts); + case unconfirmedTransactionsHashSelector: + case getMemoizedMetaMaskIdentities: + return {}; + default: + return undefined; + } +}; describe('Signature Request Component', () => { const store = configureMockStore()(mockState); @@ -35,6 +100,7 @@ describe('Signature Request Component', () => { let messageData; beforeEach(() => { + useSelector.mockImplementation(generateUseSelectorRouter(mockStore)); messageData = { domain: { chainId: 97, @@ -84,7 +150,17 @@ describe('Signature Request Component', () => { }); it('should match snapshot when we want to switch to fiat', () => { + useSelector.mockImplementation( + generateUseSelectorRouter({ + ...mockStore, + metamask: { + ...mockStore.metamask, + conversionRate: 231.06, + }, + }), + ); const msgParams = { + from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', data: JSON.stringify(messageData), version: 'V4', origin: 'test', @@ -95,7 +171,6 @@ describe('Signature Request Component', () => { txData={{ msgParams, }} - conversionRate={1567} />, store, ); @@ -105,6 +180,7 @@ describe('Signature Request Component', () => { it('should match snapshot when we are using eth', () => { const msgParams = { + from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', data: JSON.stringify(messageData), version: 'V4', origin: 'test', @@ -115,7 +191,6 @@ describe('Signature Request Component', () => { txData={{ msgParams, }} - conversionRate={null} />, store, ); @@ -125,6 +200,7 @@ describe('Signature Request Component', () => { it('should render navigation', () => { const msgParams = { + from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', data: JSON.stringify(messageData), version: 'V4', origin: 'test', @@ -135,7 +211,6 @@ describe('Signature Request Component', () => { txData={{ msgParams, }} - conversionRate={null} />, store, ); @@ -149,6 +224,7 @@ describe('Signature Request Component', () => { do_not_display: 'two', }; const msgParams = { + from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', data: JSON.stringify(messageData), version: 'V4', origin: 'test', @@ -159,7 +235,6 @@ describe('Signature Request Component', () => { txData={{ msgParams, }} - conversionRate={null} />, store, ); @@ -171,7 +246,17 @@ describe('Signature Request Component', () => { }); it('should not render a reject multiple requests link if there is not multiple requests', () => { + useSelector.mockImplementation( + generateUseSelectorRouter({ + ...mockStore, + metamask: { + ...mockStore.metamask, + unapprovedTypedMessagesCount: 0, + }, + }), + ); const msgParams = { + from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', data: JSON.stringify(messageData), version: 'V4', origin: 'test', @@ -182,7 +267,6 @@ describe('Signature Request Component', () => { txData={{ msgParams, }} - conversionRate={null} />, store, ); @@ -194,6 +278,7 @@ describe('Signature Request Component', () => { it('should render a reject multiple requests link if there is multiple requests (greater than 1)', () => { const msgParams = { + from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', data: JSON.stringify(messageData), version: 'V4', origin: 'test', @@ -204,8 +289,6 @@ describe('Signature Request Component', () => { txData={{ msgParams, }} - conversionRate={null} - unapprovedMessagesCount={2} />, store, ); @@ -217,6 +300,7 @@ describe('Signature Request Component', () => { it('should call reject all button when button is clicked', () => { const msgParams = { + from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', data: JSON.stringify(messageData), version: 'V4', origin: 'test', @@ -227,8 +311,6 @@ describe('Signature Request Component', () => { txData={{ msgParams, }} - conversionRate={null} - unapprovedMessagesCount={2} />, store, ); @@ -242,6 +324,7 @@ describe('Signature Request Component', () => { it('should render text of reject all button', () => { const msgParams = { + from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', data: JSON.stringify(messageData), version: 'V4', origin: 'test', @@ -252,8 +335,6 @@ describe('Signature Request Component', () => { txData={{ msgParams, }} - conversionRate={null} - unapprovedMessagesCount={2} />, store, ); @@ -263,6 +344,7 @@ describe('Signature Request Component', () => { it('should render SecurityProviderBannerMessage component properly', () => { const msgParams = { + from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', data: JSON.stringify(messageData), version: 'V4', origin: 'test', @@ -271,7 +353,6 @@ describe('Signature Request Component', () => { const { queryByText } = renderWithProvider( { reason_header: 'Some reason header...', }, }} - unapprovedMessagesCount={2} />, store, ); @@ -296,6 +376,7 @@ describe('Signature Request Component', () => { it('should not render SecurityProviderBannerMessage component when flagAsDangerous is not malicious', () => { const msgParams = { + from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', data: JSON.stringify(messageData), version: 'V4', origin: 'test', @@ -304,14 +385,12 @@ describe('Signature Request Component', () => { const { queryByText } = renderWithProvider( , store, ); @@ -327,27 +406,39 @@ describe('Signature Request Component', () => { it('should render a warning when the selected account is not the one being used to sign', () => { const msgParams = { + from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', data: JSON.stringify(messageData), version: 'V4', origin: 'test', }; + useSelector.mockImplementation( + generateUseSelectorRouter({ + ...mockStore, + metamask: { + ...mockStore.metamask, + selectedAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + accounts: { + ...mockStore.metamask.accounts, + '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': { + address: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + balance: '0x0', + name: 'Account 1', + }, + }, + }, + }), + ); + const { container } = renderWithProvider( , store, ); diff --git a/ui/components/app/snaps/snap-legacy-authorship-header/index.js b/ui/components/app/snaps/snap-legacy-authorship-header/index.js new file mode 100644 index 000000000000..608dfb6e5346 --- /dev/null +++ b/ui/components/app/snaps/snap-legacy-authorship-header/index.js @@ -0,0 +1 @@ +export { default } from './snap-legacy-authorship-header'; diff --git a/ui/components/app/snaps/snap-legacy-authorship-header/snap-legacy-authorship-header.js b/ui/components/app/snaps/snap-legacy-authorship-header/snap-legacy-authorship-header.js new file mode 100644 index 000000000000..0d2f3e66b807 --- /dev/null +++ b/ui/components/app/snaps/snap-legacy-authorship-header/snap-legacy-authorship-header.js @@ -0,0 +1,91 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { useSelector } from 'react-redux'; +import { + BackgroundColor, + TextColor, + TextVariant, + AlignItems, + FontWeight, + Display, + FlexDirection, + BlockSize, + BorderColor, + BorderRadius, +} from '../../../../helpers/constants/design-system'; +import { + getSnapName, + removeSnapIdPrefix, +} from '../../../../helpers/utils/util'; + +import { Box, Text } from '../../../component-library'; +import { getTargetSubjectMetadata } from '../../../../selectors'; +import SnapAvatar from '../snap-avatar'; + +const SnapLegacyAuthorshipHeader = ({ + snapId, + className, + marginLeft, + marginRight, +}) => { + const packageName = snapId && removeSnapIdPrefix(snapId); + + const subjectMetadata = useSelector((state) => + getTargetSubjectMetadata(state, snapId), + ); + + const friendlyName = snapId && getSnapName(snapId, subjectMetadata); + + return ( + + + + + + + {friendlyName} + + + {packageName} + + + + ); +}; + +SnapLegacyAuthorshipHeader.propTypes = { + /** + * The id of the snap + */ + snapId: PropTypes.string, + /** + * The className of the SnapLegacyAuthorshipHeader + */ + className: PropTypes.string, + marginLeft: PropTypes.number, + marginRight: PropTypes.number, +}; + +export default SnapLegacyAuthorshipHeader; diff --git a/ui/components/app/snaps/snap-legacy-authorship-header/snap-legacy-authorship-header.stories.js b/ui/components/app/snaps/snap-legacy-authorship-header/snap-legacy-authorship-header.stories.js new file mode 100644 index 000000000000..6e71f4ee61d5 --- /dev/null +++ b/ui/components/app/snaps/snap-legacy-authorship-header/snap-legacy-authorship-header.stories.js @@ -0,0 +1,21 @@ +import React from 'react'; +import SnapLegacyAuthorshipHeader from './snap-legacy-authorship-header'; + +export default { + title: 'Components/App/Snaps/SnapLegacyAuthorshipHeader', + + component: SnapLegacyAuthorshipHeader, + argTypes: { + snapId: { + control: 'text', + }, + }, +}; + +export const DefaultStory = (args) => ; + +DefaultStory.storyName = 'Default'; + +DefaultStory.args = { + snapId: 'npm:@metamask/test-snap-bip44', +}; diff --git a/ui/components/app/transaction-list/transaction-list.component.js b/ui/components/app/transaction-list/transaction-list.component.js index 65649adcec1c..825ace18c8fa 100644 --- a/ui/components/app/transaction-list/transaction-list.component.js +++ b/ui/components/app/transaction-list/transaction-list.component.js @@ -173,87 +173,70 @@ export default function TransactionList({ {pendingTransactions.length > 0 && ( - {pendingTransactions - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - .sort( - (a, b) => b.primaryTransaction.time - a.primaryTransaction.time, - ) - ///: END:ONLY_INCLUDE_IN - .map((dateGroup) => { - return dateGroup.transactionGroups.map( - (transactionGroup, index) => { - ///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask) - if ( - transactionGroup.initialTransaction.transactionType === - TransactionType.smart - ) { - return ( - <> - {renderDateStamp(index, dateGroup)} - - - ); - } - ///: END:ONLY_INCLUDE_IN + {pendingTransactions.map((dateGroup) => { + return dateGroup.transactionGroups.map( + (transactionGroup, index) => { + ///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask) + if ( + transactionGroup.initialTransaction.transactionType === + TransactionType.smart + ) { return ( <> {renderDateStamp(index, dateGroup)} - ); - }, - ); - })} + } + ///: END:ONLY_INCLUDE_IN + return ( + <> + {renderDateStamp(index, dateGroup)} + + + ); + }, + ); + })} )} {completedTransactions.length > 0 ? ( - completedTransactions - ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) - .sort( - (a, b) => b.primaryTransaction.time - a.primaryTransaction.time, - ) - ///: END:ONLY_INCLUDE_IN - .slice(0, limit) - .map((dateGroup) => { - return dateGroup.transactionGroups.map( - (transactionGroup, index) => { - return ( - <> - {renderDateStamp(index, dateGroup)} - {transactionGroup.initialTransaction - ?.transactionType === 'smart' ? ( - - ) : ( - - )} - - ); - }, - ); - }) + completedTransactions.slice(0, limit).map((dateGroup) => { + return dateGroup.transactionGroups.map( + (transactionGroup, index) => { + return ( + <> + {renderDateStamp(index, dateGroup)} + {transactionGroup.initialTransaction?.transactionType === + 'smart' ? ( + + ) : ( + + )} + + ); + }, + ); + }) ) : ( diff --git a/ui/components/component-library/form-text-field/form-text-field.js b/ui/components/component-library/form-text-field/form-text-field.js index e99161e64552..fbd14e261eca 100644 --- a/ui/components/component-library/form-text-field/form-text-field.js +++ b/ui/components/component-library/form-text-field/form-text-field.js @@ -5,14 +5,13 @@ import classnames from 'classnames'; import { Display, FlexDirection, - Severity, Size, } from '../../../helpers/constants/design-system'; import Box from '../../ui/box/box'; import { TextField } from '../text-field'; -import { HelpText } from '../help-text'; +import { HelpText, HelpTextSeverity } from '../help-text'; import { Label } from '../label'; export const FormTextField = ({ @@ -102,7 +101,7 @@ export const FormTextField = ({ /> {helpText && ( ` tag if the child is a `string` or a `
    ` if the child is an `object`. ```jsx -import { Size, IconColor } from '../../../helpers/constants/design-system'; +import { IconColor } from '../../../helpers/constants/design-system'; import { HelpText, Icon, IconName, IconSize } from '../../component-library'; Plain text // renders as

    Plain text

    @@ -44,41 +44,40 @@ import { HelpText, Icon, IconName, IconSize } from '../../component-library'; ### Severity -Use the `severity` prop and `SEVERITIES` object to change the severity of the `HelpText` +Use the `severity` prop and `HelpTextSeverity` enum to change the severity of the `HelpText` ```jsx -import { SEVERITIES } from '../../../helpers/constants/design-system'; -import { HelpText } from '../../component-library'; +import { HelpText, HelpTextSeverity } from '../../component-library'; HelpText without severity prop - + HelpText with severity: SEVERITY.DANGER - + HelpText with severity: SEVERITY.SUCCESS - + HelpText with severity: SEVERITY.WARNING - + HelpText with severity: SEVERITY.INFO ``` ### Color -It may be useful to change the color of the `HelpText`. Use the `color` prop and the `Color` object to change the color of the `HelpText`. Defaults to `Color.textDefault`. +It may be useful to change the color of the `HelpText`. Use the `color` prop and the `TextColor` enum to change the color of the `HelpText`. Defaults to `TextColor.textDefault`. ```jsx -import { Color } from '../../../helpers/constants/design-system'; +import { TextColor } from '../../../helpers/constants/design-system'; import { HelpText } from '../../component-library'; diff --git a/ui/components/component-library/help-text/__snapshots__/help-text.test.js.snap b/ui/components/component-library/help-text/__snapshots__/help-text.test.tsx.snap similarity index 100% rename from ui/components/component-library/help-text/__snapshots__/help-text.test.js.snap rename to ui/components/component-library/help-text/__snapshots__/help-text.test.tsx.snap diff --git a/ui/components/component-library/help-text/help-text.js b/ui/components/component-library/help-text/help-text.js deleted file mode 100644 index 354207d09a00..000000000000 --- a/ui/components/component-library/help-text/help-text.js +++ /dev/null @@ -1,68 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import classnames from 'classnames'; - -import { - Color, - TextVariant, - TextColor, - SEVERITIES, -} from '../../../helpers/constants/design-system'; - -import Box from '../../ui/box'; - -import { Text } from '../text'; - -export const HelpText = ({ - severity, - color = Color.textDefault, - className, - children, - ...props -}) => { - const severityColor = () => { - switch (severity) { - case SEVERITIES.DANGER: - return TextColor.errorDefault; - case SEVERITIES.WARNING: - return TextColor.warningDefault; - case SEVERITIES.SUCCESS: - return TextColor.successDefault; - case SEVERITIES.INFO: - return TextColor.infoDefault; - // Defaults to SEVERITIES.INFO - default: - return TextColor.textDefault; - } - }; - return ( - - {children} - - ); -}; -HelpText.propTypes = { - /** - * The color of the HelpText will be overridden if there is a severity passed - * Defaults to Color.textDefault - */ - color: PropTypes.oneOf(Object.values(TextColor)), - /** - * The content of the help-text - */ - children: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), - /** - * Additional classNames to be added to the HelpText component - */ - className: PropTypes.string, - /** - * HelpText also accepts all Box props - */ - ...Box.propTypes, -}; diff --git a/ui/components/component-library/help-text/help-text.stories.js b/ui/components/component-library/help-text/help-text.stories.tsx similarity index 58% rename from ui/components/component-library/help-text/help-text.stories.js rename to ui/components/component-library/help-text/help-text.stories.tsx index e457bf6c6c12..da14d225a4d1 100644 --- a/ui/components/component-library/help-text/help-text.stories.js +++ b/ui/components/component-library/help-text/help-text.stories.tsx @@ -1,23 +1,21 @@ import React from 'react'; +import { StoryFn, Meta } from '@storybook/react'; import { - DISPLAY, - FLEX_DIRECTION, + Display, + FlexDirection, IconColor, TextColor, - SEVERITIES, } from '../../../helpers/constants/design-system'; -import Box from '../../ui/box'; - -import { Icon, IconName, IconSize } from '..'; +import { Box, Icon, IconName, IconSize } from '..'; import { HelpText } from './help-text'; +import { HelpTextSeverity } from './help-text.types'; import README from './README.mdx'; export default { title: 'Components/ComponentLibrary/HelpText', - component: HelpText, parameters: { docs: { @@ -33,7 +31,7 @@ export default { }, severity: { control: 'select', - options: Object.values(SEVERITIES), + options: Object.values(HelpTextSeverity), }, color: { control: 'select', @@ -43,15 +41,15 @@ export default { args: { children: 'Help text', }, -}; +} as Meta; -const Template = (args) => ; +const Template: StoryFn = (args) => ; export const DefaultStory = Template.bind({}); DefaultStory.storyName = 'Default'; -export const Children = (args) => ( - +export const Children: StoryFn = (args) => ( + Plain text Text and icon @@ -66,28 +64,28 @@ export const Children = (args) => ( ); -export const SeverityStory = (args) => ( +export const SeverityStory: StoryFn = (args) => ( <> HelpText without severity prop - - HelpText with severity: SEVERITY.DANGER + + HelpText with severity: HelpTextSeverity.Danger - - HelpText with severity: SEVERITY.SUCCESS + + HelpText with severity: HelpTextSeverity.Success - - HelpText with severity: SEVERITY.WARNING + + HelpText with severity: HelpTextSeverity.Warning - - HelpText with severity: SEVERITY.INFO + + HelpText with severity: HelpTextSeverity.Info ); SeverityStory.storyName = 'Severity'; -export const ColorStory = (args) => ( - +export const ColorStory: StoryFn = (args) => ( + This HelpText default color is TextColor.textDefault diff --git a/ui/components/component-library/help-text/help-text.test.js b/ui/components/component-library/help-text/help-text.test.tsx similarity index 81% rename from ui/components/component-library/help-text/help-text.test.js rename to ui/components/component-library/help-text/help-text.test.tsx index e43fb54c548c..29cd2e46a463 100644 --- a/ui/components/component-library/help-text/help-text.test.js +++ b/ui/components/component-library/help-text/help-text.test.tsx @@ -1,10 +1,9 @@ /* eslint-disable jest/require-top-level-describe */ import { render } from '@testing-library/react'; import React from 'react'; -import { Color, SEVERITIES } from '../../../helpers/constants/design-system'; +import { TextColor } from '../../../helpers/constants/design-system'; import { Icon, IconName } from '..'; - -import { HelpText } from './help-text'; +import { HelpText, HelpTextSeverity } from '.'; describe('HelpText', () => { it('should render with text inside the HelpText', () => { @@ -34,10 +33,10 @@ describe('HelpText', () => { it('should render with severities', () => { const { getByText } = render( <> - error - success - warning - info + error + success + warning + info , ); expect(getByText('error')).toHaveClass('mm-box--color-error-default'); @@ -49,9 +48,9 @@ describe('HelpText', () => { const { getByText } = render( <> default - text default - text alternative - text muted + text default + text alternative + text muted , ); expect(getByText('default')).toHaveClass('mm-box--color-text-default'); diff --git a/ui/components/component-library/help-text/help-text.tsx b/ui/components/component-library/help-text/help-text.tsx new file mode 100644 index 000000000000..4be242562b26 --- /dev/null +++ b/ui/components/component-library/help-text/help-text.tsx @@ -0,0 +1,53 @@ +import React, { forwardRef } from 'react'; +import classnames from 'classnames'; +import { + TextVariant, + TextColor, +} from '../../../helpers/constants/design-system'; +import { Text } from '../text'; +import type { PolymorphicRef } from '../box'; +import type { TextProps } from '../text'; +import type { HelpTextProps, HelpTextComponent } from './help-text.types'; +import { HelpTextSeverity } from '.'; + +export const HelpText: HelpTextComponent = forwardRef( + ( + { + severity, + color = TextColor.textDefault, + className, + children, + ...props + }: HelpTextProps, + ref?: PolymorphicRef, + ) => { + const severityColor = () => { + switch (severity) { + case HelpTextSeverity.Danger: + return TextColor.errorDefault; + case HelpTextSeverity.Warning: + return TextColor.warningDefault; + case HelpTextSeverity.Success: + return TextColor.successDefault; + case HelpTextSeverity.Info: + return TextColor.infoDefault; + // Defaults to HelpTextSeverity.Info + default: + return TextColor.textDefault; + } + }; + + return ( + )} + > + {children} + + ); + }, +); diff --git a/ui/components/component-library/help-text/help-text.types.ts b/ui/components/component-library/help-text/help-text.types.ts new file mode 100644 index 000000000000..1945fb67dde1 --- /dev/null +++ b/ui/components/component-library/help-text/help-text.types.ts @@ -0,0 +1,35 @@ +import PropTypes from 'prop-types'; +import type { TextStyleUtilityProps } from '../text'; +import type { PolymorphicComponentPropWithRef } from '../box'; +import { Severity, TextColor } from '../../../helpers/constants/design-system'; + +export enum HelpTextSeverity { + Danger = Severity.Danger, + Warning = Severity.Warning, + Success = Severity.Success, + Info = Severity.Info, +} + +export interface HelpTextStyleUtilityProps extends TextStyleUtilityProps { + severity?: HelpTextSeverity | Severity; + /** + * The color of the HelpText will be overridden if there is a severity passed + * Defaults to Color.textDefault + */ + color?: TextColor; + /** + * The content of the help-text + */ + children: string | PropTypes.ReactNodeLike; + /** + * Additional classNames to be added to the HelpText component + */ + className?: string; +} + +export type HelpTextProps = + PolymorphicComponentPropWithRef; + +export type HelpTextComponent = ( + props: HelpTextProps, +) => React.ReactElement | null; diff --git a/ui/components/component-library/help-text/index.js b/ui/components/component-library/help-text/index.js deleted file mode 100644 index cbc88e159608..000000000000 --- a/ui/components/component-library/help-text/index.js +++ /dev/null @@ -1 +0,0 @@ -export { HelpText } from './help-text'; diff --git a/ui/components/component-library/help-text/index.ts b/ui/components/component-library/help-text/index.ts new file mode 100644 index 000000000000..85fb7f700cbb --- /dev/null +++ b/ui/components/component-library/help-text/index.ts @@ -0,0 +1,3 @@ +export { HelpText } from './help-text'; +export { HelpTextSeverity } from './help-text.types'; +export type { HelpTextProps } from './help-text.types'; diff --git a/ui/components/component-library/index.js b/ui/components/component-library/index.js index 564643063982..d225472e07e4 100644 --- a/ui/components/component-library/index.js +++ b/ui/components/component-library/index.js @@ -24,7 +24,7 @@ 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'; +export { HelpText, HelpTextSeverity } from './help-text'; export { Icon, IconName, IconSize } from './icon'; export { Label } from './label'; export { PickerNetwork } from './picker-network'; diff --git a/ui/components/component-library/text/deprecated/__snapshots__/text.test.tsx.snap b/ui/components/component-library/text/deprecated/__snapshots__/text.test.tsx.snap deleted file mode 100644 index de0c462631ec..000000000000 --- a/ui/components/component-library/text/deprecated/__snapshots__/text.test.tsx.snap +++ /dev/null @@ -1,71 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -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/index.ts b/ui/components/component-library/text/deprecated/index.ts deleted file mode 100644 index 0e4a6d9a9450..000000000000 --- a/ui/components/component-library/text/deprecated/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -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.test.tsx b/ui/components/component-library/text/deprecated/text.test.tsx deleted file mode 100644 index 4608da9c4964..000000000000 --- a/ui/components/component-library/text/deprecated/text.test.tsx +++ /dev/null @@ -1,249 +0,0 @@ -import * as React from 'react'; -import { render } from '@testing-library/react'; -import { - FontStyle, - FontWeight, - OverflowWrap, - TextAlign, - TextColor, - TextTransform, - TextVariant, - Color, -} from '../../../../helpers/constants/design-system'; -import { TextDirection } from './text.types'; -import { Text } from '.'; - -describe('Text', () => { - it('should render the Text without crashing', () => { - const { getByText } = render(Test type); - expect(getByText('Test type')).toBeDefined(); - }); - it('should render the Text with correct html elements', () => { - const { getByText, container } = render( - <> - p - h1 - h2 - h3 - h4 - h5 - h6 - span - strong - em - li - div - dt - dd - , - ); - expect(container.querySelector('p')).toBeDefined(); - expect(getByText('p')).toBeDefined(); - expect(container.querySelector('h1')).toBeDefined(); - expect(getByText('h1')).toBeDefined(); - expect(container.querySelector('h2')).toBeDefined(); - expect(getByText('h2')).toBeDefined(); - expect(container.querySelector('h3')).toBeDefined(); - expect(getByText('h3')).toBeDefined(); - expect(container.querySelector('h4')).toBeDefined(); - expect(getByText('h4')).toBeDefined(); - expect(container.querySelector('h5')).toBeDefined(); - expect(getByText('h5')).toBeDefined(); - expect(container.querySelector('h6')).toBeDefined(); - expect(getByText('h6')).toBeDefined(); - expect(container.querySelector('span')).toBeDefined(); - expect(getByText('span')).toBeDefined(); - expect(container.querySelector('strong')).toBeDefined(); - expect(getByText('strong')).toBeDefined(); - expect(container.querySelector('em')).toBeDefined(); - expect(getByText('em')).toBeDefined(); - expect(container.querySelector('li')).toBeDefined(); - expect(getByText('li')).toBeDefined(); - expect(container.querySelector('div')).toBeDefined(); - expect(getByText('div')).toBeDefined(); - expect(container.querySelector('dt')).toBeDefined(); - expect(getByText('dt')).toBeDefined(); - expect(container.querySelector('dd')).toBeDefined(); - expect(getByText('dd')).toBeDefined(); - }); - - it('should render the Text with proper variant class name', () => { - const { getByText, container } = render( - <> - 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 - , - ); - - expect(getByText('display-md')).toHaveClass('mm-text--display-md'); - expect(getByText('heading-lg')).toHaveClass('mm-text--heading-lg'); - expect(getByText('heading-md')).toHaveClass('mm-text--heading-md'); - 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 - , - ); - expect(getByText('bold')).toHaveClass('mm-text--font-weight-bold'); - expect(getByText('medium')).toHaveClass('mm-text--font-weight-medium'); - expect(getByText('normal')).toHaveClass('mm-text--font-weight-normal'); - }); - - it('should render the Text with proper text color class name', () => { - const { getByText } = render( - <> - text-default - text-alternative - text-muted - overlay-inverse - primary-default - primary-inverse - error-default - error-inverse - success-default - success-inverse - warning-inverse - info-default - info-inverse - , - ); - expect(getByText('text-default')).toHaveClass('box--color-text-default'); - expect(getByText('text-alternative')).toHaveClass( - 'box--color-text-alternative', - ); - expect(getByText('text-muted')).toHaveClass('box--color-text-muted'); - expect(getByText('primary-default')).toHaveClass( - 'box--color-primary-default', - ); - expect(getByText('primary-inverse')).toHaveClass( - 'box--color-primary-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', - ); - expect(getByText('success-inverse')).toHaveClass( - 'box--color-success-inverse', - ); - expect(getByText('warning-inverse')).toHaveClass( - 'box--color-warning-inverse', - ); - expect(getByText('info-default')).toHaveClass('box--color-info-default'); - expect(getByText('info-inverse')).toHaveClass('box--color-info-inverse'); - }); - - it('should render the Text with proper font style class name', () => { - const { getByText } = render( - <> - italic - normal - , - ); - expect(getByText('italic')).toHaveClass('mm-text--font-style-italic'); - expect(getByText('normal')).toHaveClass('mm-text--font-style-normal'); - }); - - it('should render the Text with proper text align class name', () => { - const { getByText } = render( - <> - left - center - right - justify - end - , - ); - - expect(getByText('left')).toHaveClass('mm-text--text-align-left'); - expect(getByText('center')).toHaveClass('mm-text--text-align-center'); - expect(getByText('right')).toHaveClass('mm-text--text-align-right'); - expect(getByText('justify')).toHaveClass('mm-text--text-align-justify'); - expect(getByText('end')).toHaveClass('mm-text--text-align-end'); - }); - - it('should render the Text with proper overflow wrap class name', () => { - const { getByText } = render( - <> - break-word - normal - , - ); - expect(getByText('break-word')).toHaveClass( - 'mm-text--overflow-wrap-break-word', - ); - expect(getByText('normal')).toHaveClass('mm-text--overflow-wrap-normal'); - }); - - it('should render the Text with proper ellipsis class name', () => { - const { getByText } = render( - <> - ellipsis - , - ); - expect(getByText('ellipsis')).toHaveClass('mm-text--ellipsis'); - }); - - it('should render the Text with proper text transform class name', () => { - const { getByText } = render( - <> - uppercase - lowercase - capitalize - , - ); - expect(getByText('uppercase')).toHaveClass( - 'mm-text--text-transform-uppercase', - ); - expect(getByText('lowercase')).toHaveClass( - 'mm-text--text-transform-lowercase', - ); - expect(getByText('capitalize')).toHaveClass( - 'mm-text--text-transform-capitalize', - ); - }); - it('should accept a ref prop that is passed down to the html element', () => { - const mockRef = jest.fn(); - render(); - expect(mockRef).toHaveBeenCalledTimes(1); - }); - - it('should render the Text with proper direction', () => { - const { getByText } = render( - <> - auto - ltr - rtl - , - ); - expect(getByText('auto')).toHaveAttribute('dir', 'auto'); - expect(getByText('ltr')).toHaveAttribute('dir', 'ltr'); - expect(getByText('rtl')).toHaveAttribute('dir', 'rtl'); - }); -}); diff --git a/ui/components/component-library/text/deprecated/text.tsx b/ui/components/component-library/text/deprecated/text.tsx deleted file mode 100644 index cc3a551ff868..000000000000 --- a/ui/components/component-library/text/deprecated/text.tsx +++ /dev/null @@ -1,89 +0,0 @@ -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 deleted file mode 100644 index f6d5debc57c2..000000000000 --- a/ui/components/component-library/text/deprecated/text.types.ts +++ /dev/null @@ -1,146 +0,0 @@ -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/text.tsx b/ui/components/component-library/text/text.tsx index 25d763433e45..a680560ce317 100644 --- a/ui/components/component-library/text/text.tsx +++ b/ui/components/component-library/text/text.tsx @@ -8,7 +8,7 @@ import { import { Box } from '..'; -import type { PolymorphicRef } from '../box'; +import type { PolymorphicRef, BoxProps } from '../box'; import { TextProps, TextComponent } from './text.types'; @@ -63,6 +63,7 @@ export const Text: TextComponent = React.forwardRef( [`mm-text--overflow-wrap-${overflowWrap}`]: Boolean(overflowWrap), }, ); + return ( )} > {children} 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 f4c15c41266e..a71f065807a3 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 @@ -73,7 +73,7 @@ const CustodyConfirmLink = ({ hideModal }) => { event: MetaMetricsEventName.DeeplinkClicked, }); dispatch(mmiActions.setWaitForConfirmDeepLinkDialog(false)); - dispatch(hideModal()); + hideModal(); }; return ( 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 372d90b6f51d..b6538b1d9ae4 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 @@ -27,7 +27,7 @@ exports[`Connected Site Menu should render the site menu in connected state 1`] style="bottom: 2px; right: -4px; z-index: 1;" >
    @@ -64,7 +64,7 @@ exports[`Connected Site Menu should render the site menu in not connected state style="bottom: 2px; right: -4px; z-index: 1;" >
    diff --git a/ui/components/multichain/connected-site-menu/connected-site-menu.js b/ui/components/multichain/connected-site-menu/connected-site-menu.js index 8d67867b21b9..16d7a345d9ee 100644 --- a/ui/components/multichain/connected-site-menu/connected-site-menu.js +++ b/ui/components/multichain/connected-site-menu/connected-site-menu.js @@ -64,11 +64,9 @@ export const ConnectedSiteMenu = ({ badge={ { + const { + msgParams: { from }, + } = _msgData; + + const fromAccount = getAccountByAddress(allAccounts, from); + + if (accountType === 'custody') { + try { + await dispatch(resolvePendingApproval(_msgData.id)); + completedTx(_msgData.id); + + showCustodianDeepLink({ + dispatch, + mmiActions, + txId: undefined, + custodyId: null, + fromAddress: fromAccount.address, + isSignature: true, + closeNotification: isNotification, + onDeepLinkFetched: () => undefined, + onDeepLinkShown: () => undefined, + showCustodyConfirmLink, + }); + await dispatch(mmiActions.setWaitForConfirmDeepLinkDialog(true)); + } catch (err) { + await dispatch(mmiActions.setWaitForConfirmDeepLinkDialog(true)); + await dispatch( + showModal({ + name: 'TRANSACTION_FAILED', + errorMessage: err.message, + closeNotification: true, + operationFailed: true, + }), + ); + } + } else { + // Non Custody accounts follow normal flow + await dispatch(resolvePendingApproval(_msgData.id)); + completedTx(_msgData.id); + } + }; + + return { custodySignFn }; +} diff --git a/ui/hooks/useRejectTransactionModal.js b/ui/hooks/useRejectTransactionModal.js new file mode 100644 index 000000000000..b2ce7d8a3b34 --- /dev/null +++ b/ui/hooks/useRejectTransactionModal.js @@ -0,0 +1,35 @@ +import { useDispatch, useSelector } from 'react-redux'; +import { useHistory } from 'react-router-dom'; +import { valuesFor } from '../helpers/utils/util'; +import { showModal, rejectAllMessages } from '../store/actions'; +import { clearConfirmTransaction } from '../ducks/confirm-transaction/confirm-transaction.duck'; +import { getMostRecentOverviewPage } from '../ducks/history/history'; +import { + getTotalUnapprovedMessagesCount, + unconfirmedMessagesHashSelector, +} from '../selectors'; + +export function useRejectTransactionModal() { + const dispatch = useDispatch(); + const history = useHistory(); + const mostRecentOverviewPage = useSelector(getMostRecentOverviewPage); + const unapprovedMessagesCount = useSelector(getTotalUnapprovedMessagesCount); + const unconfirmedMessagesList = useSelector(unconfirmedMessagesHashSelector); + + const handleCancelAll = () => { + dispatch( + showModal({ + name: 'REJECT_TRANSACTIONS', + onSubmit: async () => { + await dispatch(rejectAllMessages(valuesFor(unconfirmedMessagesList))); + dispatch(clearConfirmTransaction()); + history.push(mostRecentOverviewPage); + }, + unapprovedTxCount: unapprovedMessagesCount, + isRequestType: true, + }), + ); + }; + + return { handleCancelAll }; +} 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 f74dd27e94ac..f49dfe5ffd11 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 @@ -25,8 +25,8 @@ import { ButtonLink, IconName, Box, + Text, } from '../../components/component-library'; -import { Text } from '../../components/component-library/text/deprecated'; import { getCurrentChainId, getRpcPrefsForCurrentProvider, @@ -69,12 +69,12 @@ const ConfirmAddSuggestedNFT = () => { event: MetaMetricsEventName.NftAdded, category: MetaMetricsEventCategory.Wallet, sensitiveProperties: { + token_contract_address: asset.address, token_symbol: asset.symbol, token_id: asset.tokenId, - token_contract_address: asset.address, - source_connection_method: MetaMetricsTokenEventSource.Dapp, token_standard: asset.standard, asset_type: AssetType.NFT, + source: MetaMetricsTokenEventSource.Dapp, }, }); }), diff --git a/ui/pages/confirm-add-suggested-token/confirm-add-suggested-token.js b/ui/pages/confirm-add-suggested-token/confirm-add-suggested-token.js index 9867e144b08f..a972ae455655 100644 --- a/ui/pages/confirm-add-suggested-token/confirm-add-suggested-token.js +++ b/ui/pages/confirm-add-suggested-token/confirm-add-suggested-token.js @@ -132,7 +132,7 @@ const ConfirmAddSuggestedToken = () => { token_contract_address: asset.address, token_decimal_precision: asset.decimals, unlisted: asset.unlisted, - source_connection_method: MetaMetricsTokenEventSource.Dapp, + source: MetaMetricsTokenEventSource.Dapp, token_standard: TokenStandard.ERC20, asset_type: AssetType.token, }, 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 dc9d1836c44f..b8541a2cd3ea 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 @@ -21,7 +21,7 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr />
    https://metamask.github.io/test-dapp/
    @@ -195,7 +195,7 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr />
    https://metamask.github.io/test-dapp/
    @@ -380,7 +380,7 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr />
    https://metamask.github.io/test-dapp/
    @@ -565,7 +565,7 @@ exports[`ConfirmApproveContent Component should render Confirm approve page corr />
    https://metamask.github.io/test-dapp/
    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 3a81f204c27b..b25933c8bb70 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 840f5b8acce3..6c663db0be27 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/text/deprecated'; +import { Text } from '../../components/component-library'; import { Color, DISPLAY, diff --git a/ui/pages/confirm-import-token/confirm-import-token.js b/ui/pages/confirm-import-token/confirm-import-token.js index f0e37909a6d6..61bc41ff46b4 100644 --- a/ui/pages/confirm-import-token/confirm-import-token.js +++ b/ui/pages/confirm-import-token/confirm-import-token.js @@ -51,7 +51,7 @@ const ConfirmImportToken = () => { token_contract_address: pendingToken.address, token_decimal_precision: pendingToken.decimals, unlisted: pendingToken.unlisted, - source_connection_method: pendingToken.isCustom + source: pendingToken.isCustom ? MetaMetricsTokenEventSource.Custom : MetaMetricsTokenEventSource.List, token_standard: TokenStandard.ERC20, diff --git a/ui/pages/confirm-signature-request/__snapshots__/index.test.js.snap b/ui/pages/confirm-signature-request/__snapshots__/index.test.js.snap index 54852e44b798..3522d4d7a279 100644 --- a/ui/pages/confirm-signature-request/__snapshots__/index.test.js.snap +++ b/ui/pages/confirm-signature-request/__snapshots__/index.test.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Signature Request Component render should match snapshot 1`] = ` +exports[`Confirm Signature Request Component render should match snapshot 1`] = `
    -
    -
    - - M - -
    -
    - https://metamask.github.io - + class="box mm-icon mm-icon--size-md box--display-inline-block box--flex-direction-row box--color-icon-default" + style="mask-image: url('./images/icons/global.svg');" + />
    +

    + https://metamask.github.io +

    -

    Signature request -

    +
    Only sign this message if you fully understand the content and trust the requesting site.
    - -
    - Verify third-party details -
    -
    +
    + Verify third-party details +
    + +
    { +const signatureSelect = (txData, targetSubjectMetadata) => { const { type, msgParams: { version, siwe }, @@ -36,7 +38,7 @@ const signatureSelect = (txData) => { return SignatureRequest; } - if (siwe?.isSIWEMessage) { + if (siwe?.isSIWEMessage && targetSubjectMetadata !== SubjectType.Snap) { return SignatureRequestSIWE; } @@ -167,11 +169,16 @@ const ConfirmTxScreen = ({ match }) => { const txData = getTxData() || {}; const { msgParams } = txData; + + const targetSubjectMetadata = useSelector((state) => + getTargetSubjectMetadata(state, msgParams?.origin), + ); + if (!msgParams) { return ; } - const SigComponent = signatureSelect(txData); + const SigComponent = signatureSelect(txData, targetSubjectMetadata); return ( { +describe('Confirm Signature Request Component', () => { const store = configureMockStore()(mockState); describe('render', () => { diff --git a/ui/pages/create-account/connect-hardware/index.js b/ui/pages/create-account/connect-hardware/index.js index b93a8671b297..717192998837 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/__snapshots__/desktop-pairing.test.js.snap b/ui/pages/desktop-pairing/__snapshots__/desktop-pairing.test.js.snap index b61c196b7939..4a7735af9233 100644 --- a/ui/pages/desktop-pairing/__snapshots__/desktop-pairing.test.js.snap +++ b/ui/pages/desktop-pairing/__snapshots__/desktop-pairing.test.js.snap @@ -92,13 +92,13 @@ exports[`Desktop Pairing page should render otp component 1`] = `

    Pair with Desktop

    Open your MetaMask Desktop and type this code

    @@ -119,7 +119,7 @@ exports[`Desktop Pairing page should render otp component 1`] = ` >

    123456

    @@ -130,7 +130,7 @@ exports[`Desktop Pairing page should render otp component 1`] = ` >

    @@ -147,7 +147,7 @@ exports[`Desktop Pairing page should render otp component 1`] = `

    If the pairing is successful, extension will restart and you'll have to re-enter your password.

    diff --git a/ui/pages/desktop-pairing/desktop-pairing.component.js b/ui/pages/desktop-pairing/desktop-pairing.component.js index fb42e1d54ce1..06cdd3ece2a9 100644 --- a/ui/pages/desktop-pairing/desktop-pairing.component.js +++ b/ui/pages/desktop-pairing/desktop-pairing.component.js @@ -16,8 +16,7 @@ import { import Box from '../../components/ui/box/box'; import { useCopyToClipboard } from '../../hooks/useCopyToClipboard'; import Tooltip from '../../components/ui/tooltip'; -import { Button } from '../../components/component-library'; -import { Text } from '../../components/component-library/text/deprecated'; +import { Button, Text } from '../../components/component-library'; export default function DesktopPairingPage({ generateDesktopOtp, diff --git a/ui/pages/home/home.component.js b/ui/pages/home/home.component.js index a61b285fcab1..5f4eb0c296b8 100644 --- a/ui/pages/home/home.component.js +++ b/ui/pages/home/home.component.js @@ -46,8 +46,8 @@ import { ///: BEGIN:ONLY_INCLUDE_IN(build-main,build-mmi) ButtonLink, ///: END:ONLY_INCLUDE_IN + Text, } from '../../components/component-library'; -import { Text } from '../../components/component-library/text/deprecated'; import { ASSET_ROUTE, 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 c3ba507c55c7..f8d867f6aa56 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 @@ -24,8 +24,8 @@ import { BUTTON_SIZES, BUTTON_VARIANT, Box, + Text, } from '../../../components/component-library'; -import { Text } from '../../../components/component-library/text/deprecated'; import { MetaMetricsEventCategory, MetaMetricsEventName, 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 87ea155d8711..21d5935acd4e 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 @@ -33,7 +33,7 @@ exports[`CustodyAccountList renders accounts 1`] = ` for="address-0" > @@ -43,7 +43,7 @@ exports[`CustodyAccountList renders accounts 1`] = ` for="address-0" >