From fa36e3252783eca880a7ffc603ddaa07b9675950 Mon Sep 17 00:00:00 2001 From: Howard Braham Date: Thu, 9 Feb 2023 01:09:11 -0800 Subject: [PATCH] draft - fixing Import Account error messages (#16895) --- app/_locales/en/messages.json | 11 +- .../account-import-strategies/index.js | 31 +- test/e2e/tests/from-import-ui.spec.js | 2 +- .../create-account.component.js | 61 ++-- .../import-account/bottom-buttons.js | 46 +++ .../import-account/import-account.stories.js | 18 ++ .../create-account/import-account/index.js | 198 +++++++++---- .../create-account/import-account/index.scss | 90 ------ .../create-account/import-account/json.js | 247 +++++----------- .../import-account/private-key.js | 184 +++--------- ui/pages/create-account/index.scss | 44 --- .../create-account/new-account.stories.js | 10 +- ui/store/actions.ts | 271 +++++++++--------- 13 files changed, 510 insertions(+), 703 deletions(-) create mode 100644 ui/pages/create-account/import-account/bottom-buttons.js create mode 100644 ui/pages/create-account/import-account/import-account.stories.js delete mode 100644 ui/pages/create-account/import-account/index.scss diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index b1ecc6aa752e..35074ca55326 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1609,8 +1609,17 @@ "importAccountError": { "message": "Error importing account." }, + "importAccountErrorIsSRP": { + "message": "You have entered a Secret Recovery Phrase (or mnemonic). To import an account here, you have to enter a private key, which is a hexadecimal string of length 64." + }, + "importAccountErrorNotAValidPrivateKey": { + "message": "This is not a valid private key. You have entered a hexadecimal string, but it must be 64 characters long." + }, + "importAccountErrorNotHexadecimal": { + "message": "This is not a valid private key. You must enter a hexadecimal string of length 64." + }, "importAccountMsg": { - "message": "Imported accounts will not be associated with your originally created MetaMask account Secret Recovery Phrase. Learn more about imported accounts" + "message": "Imported accounts won’t be associated with your MetaMask Secret Recovery Phrase. Learn more about imported accounts" }, "importMyWallet": { "message": "Import my wallet" diff --git a/app/scripts/account-import-strategies/index.js b/app/scripts/account-import-strategies/index.js index 61243985ee8f..2c59e6aad7c3 100644 --- a/app/scripts/account-import-strategies/index.js +++ b/app/scripts/account-import-strategies/index.js @@ -1,9 +1,10 @@ -import log from 'loglevel'; +import { bufferToHex, isValidPrivate, toBuffer } from 'ethereumjs-util'; import Wallet from 'ethereumjs-wallet'; import importers from 'ethereumjs-wallet/thirdparty'; -import { toBuffer, isValidPrivate, bufferToHex } from 'ethereumjs-util'; -import { addHexPrefix } from '../lib/util'; +import { ethers } from 'ethers'; +import log from 'loglevel'; import { stripHexPrefix } from '../../../shared/modules/hexstring-utils'; +import { addHexPrefix } from '../lib/util'; const accountImporter = { async importAccount(strategy, args) { @@ -15,14 +16,30 @@ const accountImporter = { strategies: { 'Private Key': (privateKey) => { if (!privateKey) { - throw new Error('Cannot import an empty key.'); + throw new Error('Cannot import an empty key.'); // It should never get here, because this should be stopped in the UI + } + + // Check if the user has entered an SRP by mistake instead of a private key + if (ethers.utils.isValidMnemonic(privateKey.trim())){ + throw new Error('t(importAccountErrorIsSRP)'); } + privateKey = privateKey.replace(/\s+/g, ''); // Remove all whitespace + const prefixed = addHexPrefix(privateKey); - const buffer = toBuffer(prefixed); + let buffer; + try { + buffer = toBuffer(prefixed); + } catch (e) { + throw new Error('t(importAccountErrorNotHexadecimal)'); + } - if (!isValidPrivate(buffer)) { - throw new Error('Cannot import invalid private key.'); + try { + if (!isValidPrivate(buffer)) { + throw new Error('t(importAccountErrorNotAValidPrivateKey)'); + } + } catch (e) { + throw new Error('t(importAccountErrorNotAValidPrivateKey)'); } const stripped = stripHexPrefix(prefixed); diff --git a/test/e2e/tests/from-import-ui.spec.js b/test/e2e/tests/from-import-ui.spec.js index e09da607bea2..7f10a6386b9e 100644 --- a/test/e2e/tests/from-import-ui.spec.js +++ b/test/e2e/tests/from-import-ui.spec.js @@ -315,7 +315,7 @@ describe('MetaMask Import UI', function () { await driver.clickElement('.account-menu__icon'); await driver.clickElement({ text: 'Import account', tag: 'div' }); - await driver.clickElement('.new-account-import-form__select'); + await driver.clickElement('#new-account-import-form__select'); await driver.clickElement({ text: 'JSON File', tag: 'option' }); const fileInput = await driver.findElement('input[type="file"]'); diff --git a/ui/pages/create-account/create-account.component.js b/ui/pages/create-account/create-account.component.js index 4cba7b2619a1..d3301cc0999c 100644 --- a/ui/pages/create-account/create-account.component.js +++ b/ui/pages/create-account/create-account.component.js @@ -1,39 +1,36 @@ -import React, { Component } from 'react'; -import { Switch, Route } from 'react-router-dom'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; +import Box from '../../components/ui/box'; import { - NEW_ACCOUNT_ROUTE, - IMPORT_ACCOUNT_ROUTE, CONNECT_HARDWARE_ROUTE, + IMPORT_ACCOUNT_ROUTE, + NEW_ACCOUNT_ROUTE } from '../../helpers/constants/routes'; -import NewAccountCreateForm from './new-account.container'; -import NewAccountImportForm from './import-account'; import ConnectHardwareForm from './connect-hardware'; +import NewAccountImportForm from './import-account'; +import NewAccountCreateForm from './new-account.container'; -export default class CreateAccountPage extends Component { - render() { - return ( -
-
- - - - - -
-
- ); - } +export default function CreateAccountPage() { + return ( + + + + + + + + ); } diff --git a/ui/pages/create-account/import-account/bottom-buttons.js b/ui/pages/create-account/import-account/bottom-buttons.js new file mode 100644 index 000000000000..634d8faf0687 --- /dev/null +++ b/ui/pages/create-account/import-account/bottom-buttons.js @@ -0,0 +1,46 @@ +import React from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { + ButtonPrimary, + ButtonSecondary, +} from '../../../components/component-library'; +import Box from '../../../components/ui/box/box'; +import { + BLOCK_SIZES, + JustifyContent, +} from '../../../helpers/constants/design-system'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import * as actions from '../../../store/actions'; + +export default function BottomButtons({ + importAccountFunc, + isPrimaryDisabled, +}) { + const t = useI18nContext(); + const dispatch = useDispatch(); + const warning = useSelector((state) => state.appState.warning); + + return ( + + { + dispatch(actions.hideWarning()); + history.back(); + }} + > + {t('cancel')} + + + {t('import')} + + + ); +} diff --git a/ui/pages/create-account/import-account/import-account.stories.js b/ui/pages/create-account/import-account/import-account.stories.js new file mode 100644 index 000000000000..3f6cbfe7c821 --- /dev/null +++ b/ui/pages/create-account/import-account/import-account.stories.js @@ -0,0 +1,18 @@ +import React from 'react'; +import NewAccountImportForm from '.'; +import Box from '../../../components/ui/box'; +import { _setBackgroundConnection } from '../../../store/action-queue'; + +export default { + title: 'Pages/CreateAccount/ImportAccount', +}; + +export const DefaultStory = (args) => { + return ( + + + + ); +}; + +DefaultStory.storyName = 'Default'; diff --git a/ui/pages/create-account/import-account/index.js b/ui/pages/create-account/import-account/index.js index c45ca4d1970c..7ce179d932ce 100644 --- a/ui/pages/create-account/import-account/index.js +++ b/ui/pages/create-account/import-account/index.js @@ -1,79 +1,157 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; - +import React, { useContext, useState } from 'react'; +import { useDispatch } from 'react-redux'; +import { EVENT, EVENT_NAMES } from '../../../../shared/constants/metametrics'; +import { ButtonLink, Label, Text } from '../../../components/component-library'; +import Box from '../../../components/ui/box'; import Dropdown from '../../../components/ui/dropdown'; +import { MetaMetricsContext } from '../../../contexts/metametrics'; +import { + BLOCK_SIZES, + BorderColor, + FONT_WEIGHT, + JustifyContent, + Size, + TextVariant, +} from '../../../helpers/constants/design-system'; +import ZENDESK_URLS from '../../../helpers/constants/zendesk-url'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { useRouting } from '../../../hooks/useRouting'; +import * as actions from '../../../store/actions'; // Subviews -import ZENDESK_URLS from '../../../helpers/constants/zendesk-url'; import JsonImportView from './json'; import PrivateKeyImportView from './private-key'; -export default class AccountImportSubview extends Component { - static contextTypes = { - t: PropTypes.func, - }; +export default function NewAccountImportForm() { + const t = useI18nContext(); + const dispatch = useDispatch(); + const trackEvent = useContext(MetaMetricsContext); + const { navigateToMostRecentOverviewPage } = useRouting(); + + const menuItems = [t('privateKey'), t('jsonFile')]; - state = {}; + const [type, setType] = useState(menuItems[0]); - getMenuItemTexts() { - return [this.context.t('privateKey'), this.context.t('jsonFile')]; + function importAccount(strategy, importArgs) { + dispatch(actions.importNewAccount(strategy, importArgs)) + .then(({ selectedAddress, warningMessage }) => { + if (warningMessage) { + translateWarning(warningMessage); + } else if (selectedAddress) { + trackImportEvent(strategy, true); + dispatch(actions.hideWarning()); + navigateToMostRecentOverviewPage(); + } else { + dispatch(actions.displayWarning(t('importAccountError'))); + trackImportEvent(strategy, false); + } + }) + .catch((error) => translateWarning(error.message)); } - renderImportView() { - const { type } = this.state; - const menuItems = this.getMenuItemTexts(); - const current = type || menuItems[0]; + function trackImportEvent(strategy, wasSuccessful) { + const account_import_type = + strategy === 'Private Key' + ? EVENT.ACCOUNT_IMPORT_TYPES.PRIVATE_KEY + : EVENT.ACCOUNT_IMPORT_TYPES.JSON; - switch (current) { - case this.context.t('privateKey'): - return ; - case this.context.t('jsonFile'): - return ; - default: - return ; + const event = wasSuccessful + ? EVENT_NAMES.ACCOUNT_ADDED + : EVENT_NAMES.ACCOUNT_ADD_FAILED; + + trackEvent({ + category: EVENT.CATEGORIES.ACCOUNTS, + event, + properties: { + account_type: EVENT.ACCOUNT_TYPES.IMPORTED, + account_import_type, + }, + }); + } + + /** + * @param {string} message an Error/Warning message caught in importAccount() + * This function receives a message that is a string like 't(importAccountErrorNotHexadecimal)' + * and feeds it through useI18nContext + */ + function translateWarning(message) { + if (message && !message.startsWith('t(')) { + // This is just a normal error message + dispatch(actions.displayWarning(message)); + } else { + // This is an error message in a form like + // `t(importAccountErrorNotHexadecimal)` + // so slice off the first 2 chars and last char, and feed to i18n + dispatch(actions.displayWarning(t(message.slice(2, -1)))); } } - render() { - const menuItems = this.getMenuItemTexts(); - const { type } = this.state; - const { t } = this.context; + function PrivateKeyOrJson() { + switch (type) { + case menuItems[0]: + return ; + case menuItems[1]: + return ; + } + } + + return ( + <> + + {t('importAccount')} + + {t('importAccountMsg') + ' '} + + {t('here')} + + + + + + + + + + ); +} +export function moreInfoLink() { + global.platform.openTab({ + url: ZENDESK_URLS.IMPORTED_ACCOUNTS, + }); +} + +export function getLoadingMessage(strategy) { + if (strategy === 'JSON File') { return ( - <> -
-
{t('importAccount')}
-
- {t('importAccountMsg')} - { - global.platform.openTab({ - url: ZENDESK_URLS.IMPORTED_ACCOUNTS, - }); - }} - > - {t('here')} - -
-
-
-
-
- {t('selectType')} -
- ({ value: text }))} - selectedOption={type || menuItems[0]} - onChange={(value) => { - this.setState({ type: value }); - }} - /> -
- {this.renderImportView()} -
- + +
+ Expect this JSON import to take a few minutes and freeze MetaMask. +
+
+ We apologize, and we will make it faster in the future. +
); } + + return ''; } diff --git a/ui/pages/create-account/import-account/index.scss b/ui/pages/create-account/import-account/index.scss deleted file mode 100644 index e0d62bf6baf2..000000000000 --- a/ui/pages/create-account/import-account/index.scss +++ /dev/null @@ -1,90 +0,0 @@ -.new-account-info-link { - cursor: pointer; - text-decoration: underline; - color: var(--color-primary-default); - margin-inline-start: 4px; -} - -.new-account-import-form { - display: flex; - flex-flow: column; - align-items: center; - padding: 0 30px 30px; - - @include screen-sm-max { - padding: 0 22px 22px; - } - - &__select-section { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: 29px; - width: 100%; - } - - &__select-label { - @include Paragraph; - - color: var(--color-text-muted); - } - - &__select { - width: 210px; - display: flex; - align-items: center; - } - - &__private-key-password-container { - display: flex; - flex-flow: column; - align-items: center; - width: 100%; - } - - &__instruction { - @include Paragraph; - - color: var(--color-text-muted); - align-self: flex-start; - } - - &__private-key { - display: flex; - flex-flow: column; - align-items: flex-start; - margin-top: 34px; - } - - &__help-link { - color: var(--color-primary-default); - } - - &__input-password { - @include Paragraph; - - height: 54px; - width: 315px; - border: 1px solid var(--color-border-default); - border-radius: 4px; - background-color: var(--color-background-default); - color: var(--color-text-default); - margin-top: 16px; - padding: 0 20px; - } - - &__json { - display: flex; - flex-flow: column; - align-items: center; - margin-top: 29px; - width: 100%; - } - - &__buttons { - margin-top: 39px; - display: flex; - width: 100%; - justify-content: space-between; - } -} diff --git a/ui/pages/create-account/import-account/json.js b/ui/pages/create-account/import-account/json.js index cea49772aee8..33d091515a3e 100644 --- a/ui/pages/create-account/import-account/json.js +++ b/ui/pages/create-account/import-account/json.js @@ -1,189 +1,74 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { withRouter } from 'react-router-dom'; -import { compose } from 'redux'; -import { connect } from 'react-redux'; +import React, { useState } from 'react'; +import { useSelector } from 'react-redux'; import FileInput from 'react-simple-file-input'; -import * as actions from '../../../store/actions'; -import { getMetaMaskAccounts } from '../../../selectors'; -import Button from '../../../components/ui/button'; -import { EVENT, EVENT_NAMES } from '../../../../shared/constants/metametrics'; -import { getMostRecentOverviewPage } from '../../../ducks/history/history'; -import ZENDESK_URLS from '../../../helpers/constants/zendesk-url'; - -class JsonImportSubview extends Component { - state = { - fileContents: '', - isEmpty: true, - }; - - inputRef = React.createRef(); - - render() { - const { error, history, mostRecentOverviewPage } = this.props; - const enabled = !this.state.isEmpty && this.state.fileContents !== ''; - - return ( -
-

{this.context.t('usedByClients')}

- - {this.context.t('fileImportFail')} - - - this.checkInputEmpty()} - ref={this.inputRef} - /> -
- - -
- {error ? {error} : null} -
- ); - } - - onLoad(event) { - this.setState({ - fileContents: event.target.result, - }); - } - - createKeyringOnEnter(event) { - if (event.key === 'Enter') { +import { moreInfoLink } from '.'; +import { ButtonLink, Text } from '../../../components/component-library'; +import FormField from '../../../components/ui/form-field/'; +import { + Size, + TextVariant, + TEXT_ALIGN, +} from '../../../helpers/constants/design-system'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import BottomButtons from './bottom-buttons'; + +export default function JsonImportSubview({ importAccountFunc }) { + const t = useI18nContext(); + const warning = useSelector((state) => state.appState.warning); + const [password, setPassword] = useState(''); + const [fileContents, setFileContents] = useState(''); + + const isPrimaryDisabled = password === '' || fileContents === ''; + + function handleKeyPress(event) { + if (!isPrimaryDisabled && event.key === 'Enter') { event.preventDefault(); - this.createNewKeychain(); + _importAccountFunc(); } } - createNewKeychain() { - const { - firstAddress, - displayWarning, - history, - importNewJsonAccount, - mostRecentOverviewPage, - setSelectedAddress, - } = this.props; - const { fileContents } = this.state; - const { t } = this.context; - - if (!fileContents) { - const message = t('needImportFile'); - displayWarning(message); - return; - } - - const password = this.inputRef.current.value; - - importNewJsonAccount([fileContents, password]) - .then(({ selectedAddress }) => { - if (selectedAddress) { - history.push(mostRecentOverviewPage); - this.context.trackEvent({ - category: EVENT.CATEGORIES.ACCOUNTS, - event: EVENT_NAMES.ACCOUNT_ADDED, - properties: { - account_type: EVENT.ACCOUNT_TYPES.IMPORTED, - account_import_type: EVENT.ACCOUNT_IMPORT_TYPES.JSON, - }, - }); - displayWarning(null); - } else { - displayWarning(t('importAccountError')); - this.context.trackEvent({ - category: EVENT.CATEGORIES.ACCOUNTS, - event: EVENT_NAMES.ACCOUNT_ADD_FAILED, - properties: { - account_type: EVENT.ACCOUNT_TYPES.IMPORTED, - account_import_type: EVENT.ACCOUNT_IMPORT_TYPES.JSON, - }, - }); - setSelectedAddress(firstAddress); - } - }) - .catch((err) => err && displayWarning(err.message || err)); + function _importAccountFunc() { + importAccountFunc('JSON File', [fileContents, password]); } - checkInputEmpty() { - const password = this.inputRef.current.value; - let isEmpty = true; - if (password !== '') { - isEmpty = false; - } - this.setState({ isEmpty }); - } + return ( + <> + + {t('usedByClients')} + + {t('fileImportFail')} + + + + setFileContents(event.target.result)} + style={{ + padding: '20px 0px 12px 15%', + fontSize: '15px', + display: 'flex', + justifyContent: 'center', + width: '100%', + }} + /> + + + + + + ); } - -JsonImportSubview.propTypes = { - error: PropTypes.string, - displayWarning: PropTypes.func, - firstAddress: PropTypes.string, - importNewJsonAccount: PropTypes.func, - history: PropTypes.object, - setSelectedAddress: PropTypes.func, - mostRecentOverviewPage: PropTypes.string.isRequired, -}; - -const mapStateToProps = (state) => { - return { - error: state.appState.warning, - firstAddress: Object.keys(getMetaMaskAccounts(state))[0], - mostRecentOverviewPage: getMostRecentOverviewPage(state), - }; -}; - -const mapDispatchToProps = (dispatch) => { - return { - displayWarning: (warning) => dispatch(actions.displayWarning(warning)), - importNewJsonAccount: (options) => - dispatch(actions.importNewAccount('JSON File', options)), - setSelectedAddress: (address) => - dispatch(actions.setSelectedAddress(address)), - }; -}; - -JsonImportSubview.contextTypes = { - t: PropTypes.func, - trackEvent: PropTypes.func, -}; - -export default compose( - withRouter, - connect(mapStateToProps, mapDispatchToProps), -)(JsonImportSubview); diff --git a/ui/pages/create-account/import-account/private-key.js b/ui/pages/create-account/import-account/private-key.js index f1ee9f5d5306..01825258591e 100644 --- a/ui/pages/create-account/import-account/private-key.js +++ b/ui/pages/create-account/import-account/private-key.js @@ -1,160 +1,44 @@ -import React, { Component } from 'react'; -import { withRouter } from 'react-router-dom'; -import { compose } from 'redux'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import * as actions from '../../../store/actions'; -import { getMetaMaskAccounts } from '../../../selectors'; -import Button from '../../../components/ui/button'; -import { getMostRecentOverviewPage } from '../../../ducks/history/history'; -import { EVENT, EVENT_NAMES } from '../../../../shared/constants/metametrics'; +import React, { useEffect, useState } from 'react'; +import { useSelector } from 'react-redux'; +import FormField from '../../../components/ui/form-field'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import BottomButtons from './bottom-buttons'; -class PrivateKeyImportView extends Component { - static contextTypes = { - t: PropTypes.func, - trackEvent: PropTypes.func, - }; +export default function PrivateKeyImportView({ importAccountFunc }) { + const t = useI18nContext(); + const [privateKey, setPrivateKey] = useState(''); - static propTypes = { - importNewAccount: PropTypes.func.isRequired, - history: PropTypes.object.isRequired, - displayWarning: PropTypes.func.isRequired, - setSelectedAddress: PropTypes.func.isRequired, - firstAddress: PropTypes.string.isRequired, - error: PropTypes.node, - mostRecentOverviewPage: PropTypes.string.isRequired, - }; + const warning = useSelector((state) => state.appState.warning); - inputRef = React.createRef(); - - state = { isEmpty: true }; - - createNewKeychain() { - const privateKey = this.inputRef.current.value; - const { - importNewAccount, - history, - displayWarning, - mostRecentOverviewPage, - setSelectedAddress, - firstAddress, - } = this.props; - const { t } = this.context; - - importNewAccount('Private Key', [privateKey]) - .then(({ selectedAddress }) => { - if (selectedAddress) { - this.context.trackEvent({ - category: EVENT.CATEGORIES.ACCOUNTS, - event: EVENT_NAMES.ACCOUNT_ADDED, - properties: { - account_type: EVENT.ACCOUNT_TYPES.IMPORTED, - account_import_type: EVENT.ACCOUNT_IMPORT_TYPES.PRIVATE_KEY, - }, - }); - history.push(mostRecentOverviewPage); - displayWarning(null); - } else { - displayWarning(t('importAccountError')); - this.context.trackEvent({ - category: EVENT.CATEGORIES.ACCOUNTS, - event: EVENT_NAMES.ACCOUNT_ADD_FAILED, - properties: { - account_type: EVENT.ACCOUNT_TYPES.IMPORTED, - account_import_type: EVENT.ACCOUNT_IMPORT_TYPES.PRIVATE_KEY, - }, - }); - setSelectedAddress(firstAddress); - } - }) - .catch((err) => err && displayWarning(err.message || err)); - } - - createKeyringOnEnter = (event) => { - if (event.key === 'Enter') { + function handleKeyPress(event) { + if (privateKey !== '' && event.key === 'Enter') { event.preventDefault(); - this.createNewKeychain(); - } - }; - - checkInputEmpty() { - const privateKey = this.inputRef.current.value; - let isEmpty = true; - if (privateKey !== '') { - isEmpty = false; + _importAccountFunc(); } - this.setState({ isEmpty }); } - render() { - const { error, displayWarning } = this.props; - - return ( -
- - {this.context.t('pastePrivateKey')} - -
- this.createKeyringOnEnter(e)} - onChange={() => this.checkInputEmpty()} - ref={this.inputRef} - autoFocus - /> -
-
- - -
- {error ? {error} : null} -
- ); + function _importAccountFunc() { + importAccountFunc('Private Key', [privateKey]); } -} - -export default compose( - withRouter, - connect(mapStateToProps, mapDispatchToProps), -)(PrivateKeyImportView); - -function mapStateToProps(state) { - return { - error: state.appState.warning, - firstAddress: Object.keys(getMetaMaskAccounts(state))[0], - mostRecentOverviewPage: getMostRecentOverviewPage(state), - }; -} -function mapDispatchToProps(dispatch) { - return { - importNewAccount: (strategy, [privateKey]) => { - return dispatch(actions.importNewAccount(strategy, [privateKey])); - }, - displayWarning: (message) => - dispatch(actions.displayWarning(message || null)), - setSelectedAddress: (address) => - dispatch(actions.setSelectedAddress(address)), - }; + return ( + <> + + + + ); } diff --git a/ui/pages/create-account/index.scss b/ui/pages/create-account/index.scss index e69031e255e4..56e4dc14173b 100644 --- a/ui/pages/create-account/index.scss +++ b/ui/pages/create-account/index.scss @@ -1,5 +1,4 @@ @import 'connect-hardware/index'; -@import 'import-account/index'; .new-account { width: 375px; @@ -17,49 +16,6 @@ @include screen-sm-min { position: absolute; } - - &__header { - display: flex; - flex-flow: column; - border-bottom: 1px solid var(--color-border-muted); - } - - &__title { - @include H2; - - color: var(--color-text-alternative); - font-weight: 500; - margin-top: 22px; - margin-left: 29px; - } - - &__tabs { - margin-left: 22px; - display: flex; - margin-top: 10px; - - &__tab { - @include H4; - - height: 54px; - padding: 15px 10px; - color: var(--color-text-muted); - text-align: center; - cursor: pointer; - } - - &__tab:hover { - color: var(--color-text-default); - border-bottom: none; - } - - &__selected { - color: var(--color-primary-default); - border-bottom: 3px solid var(--color-primary-default); - cursor: initial; - pointer-events: none; - } - } } diff --git a/ui/pages/create-account/new-account.stories.js b/ui/pages/create-account/new-account.stories.js index 5aba7498cab0..82c121dfd2f5 100644 --- a/ui/pages/create-account/new-account.stories.js +++ b/ui/pages/create-account/new-account.stories.js @@ -1,5 +1,6 @@ -import React from 'react'; import { action } from '@storybook/addon-actions'; +import React from 'react'; +import Box from '../../components/ui/box/box'; import NewAccountCreateForm from './new-account.component'; export default { @@ -15,7 +16,12 @@ export default { }; export const DefaultStory = (args) => { return ( - + + + ); }; diff --git a/ui/store/actions.ts b/ui/store/actions.ts index 7e1056171686..388c4000f5fb 100644 --- a/ui/store/actions.ts +++ b/ui/store/actions.ts @@ -102,6 +102,7 @@ import { MetaMaskReduxState, TemporaryMessageDataType, } from './store'; +import { getLoadingMessage } from '../pages/create-account/import-account'; export function goHome() { return { @@ -113,7 +114,7 @@ export function goHome() { export function tryUnlockMetamask( password: string, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); dispatch(unlockInProgress()); log.debug(`background.submitPassword`); @@ -155,7 +156,7 @@ export function createNewVaultAndRestore( password: string, seedPhrase: string, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`background.createNewVaultAndRestore`); @@ -198,7 +199,7 @@ export function createNewVaultAndRestore( export function createNewVaultAndGetSeedPhrase( password: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); try { @@ -221,7 +222,7 @@ export function createNewVaultAndGetSeedPhrase( export function unlockAndGetSeedPhrase( password: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); try { @@ -291,7 +292,7 @@ export async function verifySeedPhrase() { export function requestRevealSeedWords( password: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`background.verifyPassword`); @@ -326,7 +327,7 @@ export function fetchInfoToSync(): ThunkAction< unknown, AnyAction > { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { log.debug(`background.fetchInfoToSync`); return new Promise((resolve, reject) => { callBackgroundMethod('fetchInfoToSync', [], (err, result) => { @@ -349,7 +350,7 @@ export function resetAccount(): ThunkAction< unknown, AnyAction > { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); return new Promise((resolve, reject) => { @@ -374,7 +375,7 @@ export function resetAccount(): ThunkAction< export function removeAccount( address: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); try { @@ -409,11 +410,11 @@ export function importNewAccount( unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { let newState; - dispatch( - showLoadingIndication('This may take a while, please be patient.'), - ); + + dispatch(showLoadingIndication(getLoadingMessage(strategy))); + try { log.debug(`background.importAccountWithStrategy`); await submitRequestToBackground('importAccountWithStrategy', [ @@ -425,8 +426,8 @@ export function importNewAccount( MetaMaskReduxState['metamask'] >('getState'); } catch (err) { - dispatch(displayWarning(err)); - throw err; + console.log('actions displayWarning', err); + return { warningMessage: err.message }; } finally { dispatch(hideLoadingIndication()); } @@ -473,7 +474,7 @@ export function checkHardwareStatus( hdPath: string, ): ThunkAction, MetaMaskReduxState, unknown, AnyAction> { log.debug(`background.checkHardwareStatus`, deviceName, hdPath); - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); let unlocked = false; @@ -499,7 +500,7 @@ export function forgetDevice( deviceName: HardwareDeviceNames, ): ThunkAction { log.debug(`background.forgetDevice`, deviceName); - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); try { await submitRequestToBackground('forgetDevice', [deviceName]); @@ -604,7 +605,7 @@ export function unlockHardwareWalletAccounts( hdPath, hdPathDescription, ); - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); for (const index of indexes) { @@ -634,7 +635,7 @@ export function showQrScanner(): ThunkAction< unknown, AnyAction > { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { dispatch( showModal({ name: 'QR_SCANNER', @@ -646,7 +647,7 @@ export function showQrScanner(): ThunkAction< export function setCurrentCurrency( currencyCode: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`background.setCurrentCurrency`); try { @@ -671,7 +672,7 @@ export function signMsg( AnyAction > { log.debug('action - signMsg'); - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`actions calling background.signMessage`); let newState; @@ -703,7 +704,7 @@ export function signPersonalMsg( AnyAction > { log.debug('action - signPersonalMsg'); - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`actions calling background.signPersonalMessage`); @@ -736,7 +737,7 @@ export function decryptMsgInline( AnyAction > { log.debug('action - decryptMsgInline'); - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { log.debug(`actions calling background.decryptMessageInline`); let newState; @@ -764,7 +765,7 @@ export function decryptMsg( AnyAction > { log.debug('action - decryptMsg'); - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`actions calling background.decryptMessage`); @@ -797,7 +798,7 @@ export function encryptionPublicKeyMsg( AnyAction > { log.debug('action - encryptionPublicKeyMsg'); - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`actions calling background.encryptionPublicKey`); @@ -830,7 +831,7 @@ export function signTypedMsg( AnyAction > { log.debug('action - signTypedMsg'); - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`actions calling background.signTypedMessage`); @@ -949,7 +950,7 @@ export function updateEditableParams( unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { let updatedTransaction: TransactionMeta; try { updatedTransaction = await submitRequestToBackground( @@ -1091,7 +1092,7 @@ export function updateTransaction( unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { !dontShowLoadingIndicator && dispatch(showLoadingIndication()); try { @@ -1138,7 +1139,7 @@ export function addUnapprovedTransactionAndRouteToConfirmationPage( unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { const actionId = generateActionId(); try { log.debug('background.addUnapprovedTransaction'); @@ -1192,7 +1193,7 @@ export function updateAndApproveTx( unknown, AnyAction > { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { !dontShowLoadingIndicator && dispatch(showLoadingIndication()); return new Promise((resolve, reject) => { const actionId = generateActionId(); @@ -1246,7 +1247,7 @@ export async function getTransactions( export function completedTx( txId: number, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { dispatch({ type: actionConstants.COMPLETED_TX, value: { @@ -1268,7 +1269,7 @@ export function updateTransactionParams(txId: number, txParams: TxParams) { export function disableSnap( snapId: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('disableSnap', [snapId]); await forceUpdateMetamaskState(dispatch); }; @@ -1277,7 +1278,7 @@ export function disableSnap( export function enableSnap( snapId: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('enableSnap', [snapId]); await forceUpdateMetamaskState(dispatch); }; @@ -1286,7 +1287,7 @@ export function enableSnap( export function removeSnap( snapId: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('removeSnap', [snapId]); await forceUpdateMetamaskState(dispatch); }; @@ -1312,7 +1313,7 @@ export async function handleSnapRequest(args: { export function dismissNotifications( ids: string[], ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('dismissNotifications', [ids]); await forceUpdateMetamaskState(dispatch); }; @@ -1352,7 +1353,7 @@ export function deleteExpiredNotifications(): ThunkAction< export function markNotificationsAsRead( ids: string[], ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('markNotificationsAsRead', [ids]); await forceUpdateMetamaskState(dispatch); }; @@ -1367,7 +1368,7 @@ export function cancelMsg( unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); let newState; @@ -1395,7 +1396,7 @@ export function cancelMsg( export function cancelMsgs( msgDataList: TemporaryMessageDataType[], ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); try { @@ -1490,7 +1491,7 @@ export function cancelPersonalMsg( unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); let newState; @@ -1517,7 +1518,7 @@ export function cancelDecryptMsg( unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); let newState; @@ -1544,7 +1545,7 @@ export function cancelEncryptionPublicKeyMsg( unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); let newState; @@ -1571,7 +1572,7 @@ export function cancelTypedMsg( unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); let newState; @@ -1599,7 +1600,7 @@ export function cancelTx( unknown, AnyAction > { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { _showLoadingIndication && dispatch(showLoadingIndication()); return new Promise((resolve, reject) => { const actionId = generateActionId(); @@ -1642,7 +1643,7 @@ export function cancelTx( export function cancelTxs( txMetaList: TransactionMeta[], ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); try { @@ -1687,7 +1688,7 @@ export function markPasswordForgotten(): ThunkAction< unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { try { await new Promise((resolve, reject) => { callBackgroundMethod('markPasswordForgotten', [], (error) => { @@ -1712,7 +1713,7 @@ export function unMarkPasswordForgotten(): ThunkAction< unknown, AnyAction > { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { return new Promise((resolve) => { callBackgroundMethod('unMarkPasswordForgotten', [], () => { resolve(); @@ -1857,7 +1858,7 @@ export function lockMetamask(): ThunkAction< > { log.debug(`background.setLocked`); - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); return backgroundSetLocked() @@ -1886,7 +1887,7 @@ async function _setSelectedAddress(address: string): Promise { export function setSelectedAddress( address: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`background.setSelectedAddress`); try { @@ -1948,7 +1949,7 @@ export function addPermittedAccount( origin: string, address: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await new Promise((resolve, reject) => { callBackgroundMethod( 'addPermittedAccount', @@ -1970,7 +1971,7 @@ export function removePermittedAccount( origin: string, address: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await new Promise((resolve, reject) => { callBackgroundMethod( 'removePermittedAccount', @@ -2008,7 +2009,7 @@ export function addToken( image?: string, dontShowLoadingIndicator?: boolean, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { if (!address) { throw new Error('MetaMask - Cannot add token without address'); } @@ -2040,7 +2041,7 @@ export function addToken( export function addImportedTokens( tokensToImport: Token[], ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { try { await submitRequestToBackground('addImportedTokens', [tokensToImport]); } catch (error) { @@ -2069,7 +2070,7 @@ export function ignoreTokens({ ? tokensToIgnore : [tokensToIgnore]; - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { if (!dontShowLoadingIndicator) { dispatch(showLoadingIndication()); } @@ -2101,7 +2102,7 @@ export function addNft( tokenID: string, dontShowLoadingIndicator: boolean, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { if (!address) { throw new Error('MetaMask - Cannot add NFT without address'); } @@ -2128,7 +2129,7 @@ export function addNftVerifyOwnership( tokenID: string, dontShowLoadingIndicator: boolean, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { if (!address) { throw new Error('MetaMask - Cannot add NFT without address'); } @@ -2166,7 +2167,7 @@ export function removeAndIgnoreNft( tokenID: string, dontShowLoadingIndicator: boolean, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { if (!address) { throw new Error('MetaMask - Cannot ignore NFT without address'); } @@ -2193,7 +2194,7 @@ export function removeNft( tokenID: string, dontShowLoadingIndicator: boolean, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { if (!address) { throw new Error('MetaMask - Cannot remove NFT without address'); } @@ -2261,7 +2262,7 @@ export async function getTokenStandardAndDetails( export function addTokens( tokens: Token[] | { [address: string]: Token }, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { if (Array.isArray(tokens)) { return Promise.all( tokens.map(({ address, symbol, decimals }) => @@ -2280,7 +2281,7 @@ export function addTokens( export function rejectWatchAsset( suggestedAssetID: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); try { await submitRequestToBackground('rejectWatchAsset', [suggestedAssetID]); @@ -2299,7 +2300,7 @@ export function rejectWatchAsset( export function acceptWatchAsset( suggestedAssetID: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); try { await submitRequestToBackground('acceptWatchAsset', [suggestedAssetID]); @@ -2329,7 +2330,7 @@ export function createCancelTransaction( log.debug('background.cancelTransaction'); let newTxId: number; - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { const actionId = generateActionId(); return new Promise((resolve, reject) => { callBackgroundMethod( @@ -2365,7 +2366,7 @@ export function createSpeedUpTransaction( log.debug('background.createSpeedUpTransaction'); let newTx: TransactionMeta; - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { const actionId = generateActionId(); return new Promise((resolve, reject) => { callBackgroundMethod( @@ -2398,7 +2399,7 @@ export function createRetryTransaction( ): ThunkAction { let newTx: TransactionMeta; - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { return new Promise((resolve, reject) => { const actionId = generateActionId(); callBackgroundMethod( @@ -2430,7 +2431,7 @@ export function createRetryTransaction( export function setProviderType( type: NetworkType, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { log.debug(`background.setProviderType`, type); try { @@ -2449,7 +2450,7 @@ export function updateAndSetCustomRpc( nickname: string, rpcPrefs: RPCDefinition['rpcPrefs'], ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { log.debug( `background.updateAndSetCustomRpc: ${newRpcUrl} ${chainId} ${ ticker ?? EtherDenomination.ETH @@ -2479,7 +2480,7 @@ export function editRpc( nickname: string, rpcPrefs: RPCDefinition['rpcPrefs'], ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { log.debug(`background.delRpcTarget: ${oldRpcUrl}`); try { submitRequestToBackground('delCustomRpc', [oldRpcUrl]); @@ -2510,7 +2511,7 @@ export function setRpcTarget( ticker?: EtherDenomination, nickname?: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { log.debug( `background.setRpcTarget: ${newRpcUrl} ${chainId} ${ticker} ${nickname}`, ); @@ -2535,7 +2536,7 @@ export function rollbackToPreviousProvider(): ThunkAction< unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { try { await submitRequestToBackground('rollbackToPreviousProvider'); } catch (error) { @@ -2548,7 +2549,7 @@ export function rollbackToPreviousProvider(): ThunkAction< export function delRpcTarget( oldRpcUrl: string, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { log.debug(`background.delRpcTarget: ${oldRpcUrl}`); return new Promise((resolve, reject) => { callBackgroundMethod('delCustomRpc', [oldRpcUrl], (err) => { @@ -2683,7 +2684,7 @@ interface NftDropDownState { export function updateNftDropDownState( value: NftDropDownState, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('updateNftDropDownState', [value]); await forceUpdateMetamaskState(dispatch); }; @@ -2706,7 +2707,7 @@ interface QrCodeData { export function qrCodeDetected( qrCodeData: QrCodeData, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await dispatch({ type: actionConstants.QR_CODE_DETECTED, value: qrCodeData, @@ -2862,7 +2863,7 @@ export function setAccountLabel( account: string, label: string, ): ThunkAction, MetaMaskReduxState, unknown, AnyAction> { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`background.setAccountLabel`); @@ -2904,7 +2905,7 @@ export function buy(opts: { symbol?: CurrencySymbol; service?: string; }): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { const url = await getBuyUrl(opts); if (url) { global.platform.openTab({ url }); @@ -2933,7 +2934,7 @@ export function setFeatureFlag( unknown, AnyAction > { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); return new Promise((resolve, reject) => { callBackgroundMethod( @@ -2963,7 +2964,7 @@ export function setPreference( unknown, AnyAction > { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); return new Promise((resolve, reject) => { callBackgroundMethod( @@ -2988,7 +2989,7 @@ export function setPreference( export function setDefaultHomeActiveTabName( value: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('setDefaultHomeActiveTabName', [value]); await forceUpdateMetamaskState(dispatch); }; @@ -3022,7 +3023,7 @@ export function setCompletedOnboarding(): ThunkAction< unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); try { @@ -3085,7 +3086,7 @@ export function setParticipateInMetaMetrics( unknown, AnyAction > { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { log.debug(`background.setParticipateInMetaMetrics`); return new Promise((resolve, reject) => { callBackgroundMethod( @@ -3113,7 +3114,7 @@ export function setParticipateInMetaMetrics( export function setUseBlockie( val: boolean, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`background.setUseBlockie`); callBackgroundMethod('setUseBlockie', [val], (err) => { @@ -3128,7 +3129,7 @@ export function setUseBlockie( export function setUseNonceField( val: boolean, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`background.setUseNonceField`); try { @@ -3143,7 +3144,7 @@ export function setUseNonceField( export function setUsePhishDetect( val: boolean, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`background.setUsePhishDetect`); callBackgroundMethod('setUsePhishDetect', [val], (err) => { @@ -3158,7 +3159,7 @@ export function setUsePhishDetect( export function setUseMultiAccountBalanceChecker( val: boolean, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`background.setUseMultiAccountBalanceChecker`); callBackgroundMethod('setUseMultiAccountBalanceChecker', [val], (err) => { @@ -3173,7 +3174,7 @@ export function setUseMultiAccountBalanceChecker( export function setUseTokenDetection( val: boolean, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`background.setUseTokenDetection`); callBackgroundMethod('setUseTokenDetection', [val], (err) => { @@ -3188,7 +3189,7 @@ export function setUseTokenDetection( export function setUseNftDetection( val: boolean, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`background.setUseNftDetection`); callBackgroundMethod('setUseNftDetection', [val], (err) => { @@ -3203,7 +3204,7 @@ export function setUseNftDetection( export function setUseCurrencyRateCheck( val: boolean, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`background.setUseCurrencyRateCheck`); callBackgroundMethod('setUseCurrencyRateCheck', [val], (err) => { @@ -3218,7 +3219,7 @@ export function setUseCurrencyRateCheck( export function setOpenSeaEnabled( val: boolean, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`background.setOpenSeaEnabled`); callBackgroundMethod('setOpenSeaEnabled', [val], (err) => { @@ -3236,7 +3237,7 @@ export function detectNfts(): ThunkAction< unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`background.detectNfts`); await submitRequestToBackground('detectNfts'); @@ -3248,7 +3249,7 @@ export function detectNfts(): ThunkAction< export function setAdvancedGasFee( val: { maxBaseFee?: Hex; priorityFee?: Hex } | null, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`background.setAdvancedGasFee`); callBackgroundMethod('setAdvancedGasFee', [val], (err) => { @@ -3263,7 +3264,7 @@ export function setAdvancedGasFee( export function setTheme( val: ThemeType, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); log.debug(`background.setTheme`); try { @@ -3277,7 +3278,7 @@ export function setTheme( export function setIpfsGateway( val: string, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { log.debug(`background.setIpfsGateway`); callBackgroundMethod('setIpfsGateway', [val], (err) => { if (err) { @@ -3290,7 +3291,7 @@ export function setIpfsGateway( export function updateCurrentLocale( key: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); try { @@ -3372,7 +3373,7 @@ export function setPendingTokens(pendingTokens: { export function setSwapsLiveness( swapsLiveness: boolean, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('setSwapsLiveness', [swapsLiveness]); await forceUpdateMetamaskState(dispatch); }; @@ -3381,7 +3382,7 @@ export function setSwapsLiveness( export function setSwapsFeatureFlags( featureFlags: TemporaryFeatureFlagDef, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('setSwapsFeatureFlags', [featureFlags]); await forceUpdateMetamaskState(dispatch); }; @@ -3415,7 +3416,7 @@ export function fetchAndSetQuotes( unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { const [quotes, selectedAggId] = await submitRequestToBackground( 'fetchAndSetQuotes', [fetchParams, fetchParamsMetaData], @@ -3428,7 +3429,7 @@ export function fetchAndSetQuotes( export function setSelectedQuoteAggId( aggId: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('setSelectedQuoteAggId', [aggId]); await forceUpdateMetamaskState(dispatch); }; @@ -3437,7 +3438,7 @@ export function setSelectedQuoteAggId( export function setSwapsTokens( tokens: Token[], ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('setSwapsTokens', [tokens]); await forceUpdateMetamaskState(dispatch); }; @@ -3449,7 +3450,7 @@ export function clearSwapsQuotes(): ThunkAction< unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('clearSwapsQuotes'); await forceUpdateMetamaskState(dispatch); }; @@ -3461,7 +3462,7 @@ export function resetBackgroundSwapsState(): ThunkAction< unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('resetSwapsState'); await forceUpdateMetamaskState(dispatch); }; @@ -3470,7 +3471,7 @@ export function resetBackgroundSwapsState(): ThunkAction< export function setCustomApproveTxData( data: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('setCustomApproveTxData', [data]); await forceUpdateMetamaskState(dispatch); }; @@ -3479,7 +3480,7 @@ export function setCustomApproveTxData( export function setSwapsTxGasPrice( gasPrice: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('setSwapsTxGasPrice', [gasPrice]); await forceUpdateMetamaskState(dispatch); }; @@ -3488,7 +3489,7 @@ export function setSwapsTxGasPrice( export function setSwapsTxGasLimit( gasLimit: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('setSwapsTxGasLimit', [gasLimit, true]); await forceUpdateMetamaskState(dispatch); }; @@ -3503,7 +3504,7 @@ export function updateCustomSwapsEIP1559GasParams({ maxFeePerGas: string; maxPriorityFeePerGas: string; }): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await Promise.all([ submitRequestToBackground('setSwapsTxGasLimit', [gasLimit]), submitRequestToBackground('setSwapsTxMaxFeePerGas', [maxFeePerGas]), @@ -3521,7 +3522,7 @@ export function updateCustomSwapsEIP1559GasParams({ export function updateSwapsUserFeeLevel( swapsCustomUserFeeLevel: PriorityLevels, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('setSwapsUserFeeLevel', [ swapsCustomUserFeeLevel, ]); @@ -3532,7 +3533,7 @@ export function updateSwapsUserFeeLevel( export function setSwapsQuotesPollingLimitEnabled( quotesPollingLimitEnabled: boolean, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('setSwapsQuotesPollingLimitEnabled', [ quotesPollingLimitEnabled, ]); @@ -3543,7 +3544,7 @@ export function setSwapsQuotesPollingLimitEnabled( export function setTradeTxId( tradeTxId: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('setTradeTxId', [tradeTxId]); await forceUpdateMetamaskState(dispatch); }; @@ -3552,7 +3553,7 @@ export function setTradeTxId( export function setApproveTxId( approveTxId: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('setApproveTxId', [approveTxId]); await forceUpdateMetamaskState(dispatch); }; @@ -3564,7 +3565,7 @@ export function safeRefetchQuotes(): ThunkAction< unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('safeRefetchQuotes'); await forceUpdateMetamaskState(dispatch); }; @@ -3576,7 +3577,7 @@ export function stopPollingForQuotes(): ThunkAction< unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('stopPollingForQuotes'); await forceUpdateMetamaskState(dispatch); }; @@ -3585,7 +3586,7 @@ export function stopPollingForQuotes(): ThunkAction< export function setBackgroundSwapRouteState( routeState: '' | 'loading' | 'awaiting' | 'smartTransactionStatus', ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('setBackgroundSwapRouteState', [ routeState, ]); @@ -3599,7 +3600,7 @@ export function resetSwapsPostFetchState(): ThunkAction< unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('resetPostFetchState'); await forceUpdateMetamaskState(dispatch); }; @@ -3608,7 +3609,7 @@ export function resetSwapsPostFetchState(): ThunkAction< export function setSwapsErrorKey( errorKey: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('setSwapsErrorKey', [errorKey]); await forceUpdateMetamaskState(dispatch); }; @@ -3617,7 +3618,7 @@ export function setSwapsErrorKey( export function setInitialGasEstimate( initialAggId: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('setInitialGasEstimate', [initialAggId]); await forceUpdateMetamaskState(dispatch); }; @@ -3628,7 +3629,7 @@ export function setInitialGasEstimate( export function requestAccountsPermissionWithId( origin: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { const id = await submitRequestToBackground( 'requestAccountsPermissionWithId', [origin], @@ -3646,7 +3647,7 @@ export function requestAccountsPermissionWithId( export function approvePermissionsRequest( request: PermissionsRequest, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { callBackgroundMethod('approvePermissionsRequest', [request], (err) => { if (err) { dispatch(displayWarning(err)); @@ -3663,7 +3664,7 @@ export function approvePermissionsRequest( export function rejectPermissionsRequest( requestId: string, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { return new Promise((resolve, reject) => { callBackgroundMethod('rejectPermissionsRequest', [requestId], (err) => { if (err) { @@ -3685,7 +3686,7 @@ export function rejectPermissionsRequest( export function removePermissionsFor( subjects: Record>, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { callBackgroundMethod('removePermissionsFor', [subjects], (err) => { if (err) { dispatch(displayWarning(err)); @@ -3707,7 +3708,7 @@ export function resolvePendingApproval( id: string, value: unknown, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('resolvePendingApproval', [id, value]); // Before closing the current window, check if any additional confirmations // are added as a result of this confirmation being accepted @@ -3729,7 +3730,7 @@ export function rejectPendingApproval( id: string, error: unknown, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { await submitRequestToBackground('rejectPendingApproval', [id, error]); // Before closing the current window, check if any additional confirmations // are added as a result of this confirmation being rejected @@ -3743,7 +3744,7 @@ export function rejectPendingApproval( export function setFirstTimeFlowType( type: 'create' | 'import', ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { log.debug(`background.setFirstTimeFlowType`); callBackgroundMethod('setFirstTimeFlowType', [type], (err) => { if (err) { @@ -3808,7 +3809,7 @@ export function setLastActiveTime(): ThunkAction< unknown, AnyAction > { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { callBackgroundMethod('setLastActiveTime', [], (err) => { if (err) { dispatch(displayWarning(err)); @@ -3820,7 +3821,7 @@ export function setLastActiveTime(): ThunkAction< export function setDismissSeedBackUpReminder( value: boolean, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); await submitRequestToBackground('setDismissSeedBackUpReminder', [value]); dispatch(hideLoadingIndication()); @@ -3831,7 +3832,7 @@ export function setDisabledRpcMethodPreference( methodName: string, value: number, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); await submitRequestToBackground('setDisabledRpcMethodPreference', [ methodName, @@ -3847,7 +3848,7 @@ export function getRpcMethodPreferences(): ThunkAction< unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); await submitRequestToBackground('getRpcMethodPreferences', []); dispatch(hideLoadingIndication()); @@ -3906,7 +3907,7 @@ export function setOutdatedBrowserWarningLastShown(lastShown: number) { export function getContractMethodData( data = '', ): ThunkAction { - return async (dispatch, getState) => { + return async (dispatch: MetaMaskReduxDispatch, getState) => { const prefixedData = addHexPrefix(data); const fourBytePrefix = prefixedData.slice(0, 10); if (fourBytePrefix.length < 10) { @@ -3943,7 +3944,7 @@ export function getContractMethodData( export function setSeedPhraseBackedUp( seedPhraseBackupState: boolean, ): ThunkAction { - return (dispatch) => { + return (dispatch: MetaMaskReduxDispatch) => { log.debug(`background.setSeedPhraseBackedUp`); return new Promise((resolve, reject) => { callBackgroundMethod( @@ -4023,7 +4024,7 @@ export function getRequestAccountTabIds(): ThunkAction< unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { const requestAccountTabIds = await submitRequestToBackground<{ [origin: string]: string; }>('getRequestAccountTabIds'); @@ -4046,7 +4047,7 @@ export function getOpenMetamaskTabsIds(): ThunkAction< unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { const openMetaMaskTabIDs = await submitRequestToBackground<{ [tabId: string]: boolean; }>('getOpenMetamaskTabsIds'); @@ -4057,7 +4058,7 @@ export function getOpenMetamaskTabsIds(): ThunkAction< export function setLedgerTransportPreference( value: LedgerTransportTypes, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(showLoadingIndication()); await submitRequestToBackground('setLedgerTransportPreference', [value]); dispatch(hideLoadingIndication()); @@ -4292,7 +4293,7 @@ export function fetchSmartTransactionFees( unsignedTransaction: Partial & { chainId: string }, approveTxParams: TxParams, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { if (approveTxParams) { approveTxParams.value = '0x0'; } @@ -4365,7 +4366,7 @@ export function signAndSendSmartTransaction({ cancelFees: TemporarySmartTransactionGasFees[]; }; }): ThunkAction, MetaMaskReduxState, unknown, AnyAction> { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { const signedTransactions = await createSignedTransactions( unsignedTransaction, smartTransactionFees.fees, @@ -4405,7 +4406,7 @@ export function updateSmartTransaction( uuid: string, txMeta: TransactionMeta, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { try { await submitRequestToBackground('updateSmartTransaction', [ { @@ -4444,7 +4445,7 @@ export function setSmartTransactionsRefreshInterval( export function cancelSmartTransaction( uuid: string, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { try { await submitRequestToBackground('cancelSmartTransaction', [uuid]); } catch (err) { @@ -4530,7 +4531,7 @@ export function cancelSyncQRHardware(): ThunkAction< unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(hideLoadingIndication()); await submitRequestToBackground('cancelSyncQRHardware'); }; @@ -4549,7 +4550,7 @@ export function cancelQRHardwareSignRequest(): ThunkAction< unknown, AnyAction > { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { dispatch(hideLoadingIndication()); await submitRequestToBackground('cancelQRHardwareSignRequest'); }; @@ -4558,7 +4559,7 @@ export function cancelQRHardwareSignRequest(): ThunkAction< export function addCustomNetwork( customRpc: RPCDefinition, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { try { dispatch(setNewCustomNetworkAdded(customRpc)); await submitRequestToBackground('addCustomNetwork', [ @@ -4576,7 +4577,7 @@ export function requestAddNetworkApproval( customRpc: RPCDefinition, originIsMetaMask: boolean, ): ThunkAction { - return async (dispatch) => { + return async (dispatch: MetaMaskReduxDispatch) => { try { await submitRequestToBackground('requestAddNetworkApproval', [ customRpc,